问题
I am unable to use lldb to invoke simple, non-templated functions that take string arguments. Is there any way to get lldb to understand the C++ datatype "string", which is a commonly used datatype in C++ programs?
The sample source code here just creates a simple class with a few constructors, and then calls them (includes of "iostream" and "string" omitted):
using namespace std;
struct lldbtest{
int bar=5;
lldbtest(){bar=6;}
lldbtest(int foo){bar=foo;}
lldbtest(string fum){bar=7;}
};
int main(){
string name="fum";
lldbtest x,y(3);
cout<<x.bar<<y.bar<<endl;
return 0;
}
When compiled on Mac Maverick with
g++ -g -std=c++11 -o testconstructor testconstructor.cpp
the program runs and prints the expected output of "63".
However, when a breakpoint is set in main just before the return statement, and attempt to invoke the constructor fails with a cryptic error message:
p lldbtest(string("hey there"))
error: call to a function 'lldbtest::lldbtest(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)' ('_ZN8lldbtestC1ENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE') that is not present in the target
error: The expression could not be prepared to run in the target
Possibly relevant as well, the command:
p lldbtest(name)
prints nothing at all.
Also, calling the constructor with a string literal also failed, the standard way:
p lldbtest("foo")
gives a similar long error:
error: call to a function
'lldbtest::lldbtest(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)' ('_ZN8lldbtestC1ENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE') that is not present in the targeterror: The expression could not be prepared to run in the target
Is there any way to get lldb to understand and use the C++ "string" datatype? I have a number of functions taking string arguments and need a way to invoke these functions from the debugger. On a Mac.
回答1:
THE PROBLEM
This is due to a subtle problem with your code, that boils down to the following wording from the C++ Standard:
7.1.2p3-4
Function specifiers[dcl.fct.spec]
A function defined within a class definition is an inline function.
...
An inline function shall be defined in every translation unit in which it is odr-used, and shall have exactly the same definition in every case (3.2).
Your constructor, lldbtest(std::string)
is defined within the body of lldbtest
which means that it will implicitly be inline, which further means that the compiler will not generate any code for it, unless it is used in the translation unit.
Since the definition must be present in every translation unit that potentially calls it we can imagine the compiler saying; "heck, I don't need to do this.. if someone else uses it, they will generate the code".
lldb will look for a function definition which doesn't exist, since gcc
didn't generate one; because you didn't use it.
THE SOLUTION
If we change the definition of lldbtest
to the following I bet it will work as you intended:
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; }
But.. what about p lldbtest(name)
?
The command p
in lldb
is used to print*
information, but it can also be used to evaluate expressions.
lldbtest(name)
will not call the constructor of lldbtest
with a variable called name, it's equivalent of declaring a variable called name of type lldbtest
; ie. lldbtest name
is sementically equivalent.
回答2:
Going to answer the asked question here instead of addressing the problem with the op's code. Especially since this took me a while to figure out.
Use a string in a function invocation in lldb in C++
(This post helped greatly, and is a good read: Dancing in The Debugger)
来源:https://stackoverflow.com/questions/24104814/invoking-function-with-string-argument-with-lldb-how