Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking function with string argument from lldb: take 2

I cannot seem to use lldb to invoke functions with string parameters , at times. In this question, Invoking function with string argument with lldb: how? , I gave a simple test file illustrating the problem. A user answered that question to show how modifying the test file would fix the problem in that case.

But for more general situations I am still unable to invoke functions with string arguments from lldb.

To set this up though, I need to show two files. The first file is just like in the other question, a simple class lldbtest that defines a constructor taking a string argument. Then, another file defining a function in which the debugger will break.

The first file (without some #includes) looks like this:

 struct lldbtest{
   int bar=5;
   lldbtest();
   lldbtest(int foo);
   lldbtest(string &fum);
 };

 lldbtest::lldbtest() { bar=6; }
 lldbtest::lldbtest(int) { bar=7; }
 lldbtest::lldbtest(string&) { bar=8; }

 int main(){
   string name="fum";
   lldbtest x,y(3);
   cout<<x.bar<<y.bar<<endl;
   int zz=nothing();

   return 0;
 }

The second file looks like this:

 using namespace std;
 int nothing(){
   cout<<"hello there"<<endl;
   int n=0,m=1,r=2;
   return m+r+n;
 }

Now, when I set a breakpoint at the return statement in the second file, and evaluate:

p lldbtest(string("bar"))

I get a long error message that is quite difficult to post here but looks like this:

error: no matching conversion for functional-style cast from 'string' (aka 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >') to 'lldbtest'
 note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'string' (aka 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >') to 'const lldbtest' for 1st argument
note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'string' (aka 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >') to 'lldbtest' for 1st argument
note: candidate constructor not viable: no known conversion from 'string' (aka 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >') to 'int' for 1st argument
note: candidate constructor not viable: expects an l-value for 1st argument
note: candidate constructor not viable: requires 0 arguments, but 1 was provided
error: 1 errors parsing expression

Wow, the error message is longer than the code.

Anyway, my question is: how can I invoke functions/constructors with string parameters from lldb, from a file other than the one where the constructor was defined/declared, as here?

compilation was with g++ -g -std=c++11 . I used these same options to link the object files, also with g++ on a Mac.

like image 229
kdog Avatar asked Jun 08 '14 11:06

kdog


1 Answers

Temporaries cannot bind to lvalue references

The problem is that a temporary, string ("bar"), cannot bind to a lvalue reference, which is what the constructor you wish to use has as an argument; in other words, there's no direct issue with lldb in this case.

lldbtest::lldbtest(string &fum); // cannot be called with a temporary

To fix the problem you can change the constructor, or introduce a new one, that accepts a string const& or just a string, which will be suitable for the temporary passed during p lldbtest(string("bar")):

lldbtest::lldbtest(string const&fum); // can bind to a temporary
lldbtest::lldbtest(string fum2);      // will copy the argument, safe to use with
                                      // lvalue and rvalues (temporaries)

If you try to have the same line of code in main you will see that the compiler won't accept what you are trying to do either:

lldbtest temporary (string ("bar")); // illegal, no suitable overload found

A little example

Which can further be explained with the following little snippet:

void func (std::string&) {
  // ...
}

int main () {
  func (std::string ("bar"));
}

foo.cpp: In function ‘int main()’:
foo.cpp:8:28: error: invalid initialization of non-const reference of type ‘std::string&
                     {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string
                     {aka std::basic_string<char>}’
   func (std::string ("bar"));
                            ^
foo.cpp:3:6: note: in passing argument 1 of ‘void func(std::string&)’
 void func (std::string&) {
like image 103
Filip Roséen - refp Avatar answered Oct 06 '22 13:10

Filip Roséen - refp