gdb cannot access c_str() function of std::string in boolean expression - c++

I have a file named testing.cpp:
#include <iostream>
#include <string>
struct Foo {
std::string name;
};
int main() {
Foo* foo = new Foo;
foo->name = "hello";
std::cout << foo->name << "\n";
return 0;
}
I compiled it to a.out, and start gdb using gdb a.out.
GNU gdb (Debian 7.10-1.1) 7.10
...
Reading symbols from a.out...done.
(gdb)
I break at line 12 (std::cout << foo->name << "\n";), and run:
(gdb) break 12
Breakpoint 1 at 0x400990: file testing.cpp, line 12.
(gdb) run
Starting program: ...
Breakpoint 1, main () at testing.cpp:12
12 std::cout << foo->name << "\n";
(gdb)
It can print foo->name and foo->name.c_str():
(gdb) print foo->name
$1 = "hello"
(gdb) print foo->name.c_str()
$2 = 0x613c30 "hello"
It can print boolean expression with foo->name.c_str() in the first clause:
(gdb) print foo->name.c_str() && 1
$3 = true
But it can't when I put foo->name.c_str() in second clause:
(gdb) print 1 && foo->name.c_str()
Attempt to take address of value not located in memory.
(gdb)
Is this a bug?
Edit 1:
Use Case
I was trying to use break ... if ... to break at some point if some strings have certain values. E.g.
(gdb) break 14 if foo->name.size() == 5 && $_streq(foo->name.c_str(), "house")
Breakpoint 2 at 0x400aba: file testing.cpp, line 14
(gdb)
When I continue, gdb show the error message and break at line 14 (return 0;) even though foo->name is "hello" but not "house".
(gdb) continue
Continuing.
hello
Error in testing breakpoint condition:
Attempt to take address of value not located in memory.
Breakpoint 2, main () at testing.cpp:14
14 return 0;
(gdb)
Currently a workaround is access data member of std::string directly:
(gdb) break 14 if foo->name.size() == 5 && \
$_streq(foo->name._M_dataplus._M_p, "house")
Some Observations
Is it because my foo is pointer?
Nope. I tried to use Foo foo; instead of Foo* foo = new Foo;. Problem remains.
Does this problem apply for std::string variable created in main(), oppose to as a data member of some object?
Nope. Seems like it only applies for std::string as a data member. Code below works:
(gdb) list 4,8
4 int main() {
5 std::string name("hello");
6 std::cout << name << "\n";
7 return 0;
8 }
(gdb) break 6
Breakpoint 1 at 0x400a93: file testing.cpp, line 6
(gdb) run
Starting program: ...
Breakpoint 1, main() at testing.cpp:6
6 std::cout << name << "\n";
(gdb) print 1 && name.c_str()
$1 = true
Does this problem unique to c_str() only? How about other function?
No, this problem is not unique to c_str(). It is not even unique to std::string. Seems like it happens when we call member function of object inside another object, i.e. foo.bar.func().

Related

How do I find where a string in is saved in my virtual memory? Using gdb to Debug .cc file

I have an executable file that was compiled from a .cc file. I'm now debugging with the gdb. In line 66 of my code I have:
cout << "Mean: " << mean << endl;
I'm now trying to find where "Mean: " is saved in my virtual memory. Any tips?
I've tried different commands like find and print but have had no breakthroughs.
Does anybody have any tips?
Here are a few ways you could find the string.
Let's compile this test:
#include <iostream>
int main(int arch, char *argv[])
{
double mean = 0.5;
std::cout << "Mean: " << mean << std::endl;
}
Use disassembly. Set breakpoint on the std::cout line:
(gdb) run
Starting program: /tmp/a.out
Breakpoint 1, main (arch=1, argv=0x7fffffffe328) at t.cc:5
5 std::cout << "Mean: " << mean << std::endl;
(gdb) info line 5
Line 5 of "t.cc" starts at address 0x555555555191 <main(int, char**)+28> and ends at 0x5555555551a4 <main(int, char**)+47>.
(gdb) disas 0x555555555191,0x5555555551a4+1
Dump of assembler code from 0x555555555191 to 0x5555555551a5:
=> 0x0000555555555191 <main(int, char**)+28>: lea 0xe71(%rip),%rsi # 0x555555556009
0x0000555555555198 <main(int, char**)+35>: lea 0x2ec1(%rip),%rdi # 0x555555558060 <_ZSt4cout##GLIBCXX_3.4>
0x000055555555519f <main(int, char**)+42>: callq 0x555555555040 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc#plt>
0x00005555555551a4 <main(int, char**)+47>: movsd -0x8(%rbp),%xmm0
End of assembler dump.
Above you can see register rsi being loaded with value 0x555555556009, which is passed as second argument to the std::operator<< (). It must contain the string. Indeed:
(gdb) x/s 0x555555556009
0x555555556009: "Mean: "
Use info file to find .rodata section (in which this string resides) and find commands:
(gdb) info file
Symbols from "/tmp/a.out".
Native process:
Using the running image of child process 905.
While running this, GDB does not access memory from...
Local exec file:
`/tmp/a.out', file type elf64-x86-64.
Entry point: 0x555555555090
0x00005555555542a8 - 0x00005555555542c4 is .interp
...
0x0000555555556000 - 0x0000555555556018 is .rodata
...
(gdb) find 0x0000555555556000, 0x0000555555556018, {char[6]}"Mean: "
0x555555556009
1 pattern found.

gdb - execute current line without moving on

This has probably been asked elsewhere, but was a bit of a tricky one to google.
I am debugging some code like the following in gdb (or cgdb more specifically):
if(something) {
string a = stringMaker();
string b = stringMaker();
}
As I step through using 'n', the cursor will reach the 'string b' line. At this point I can inspect the value of a, but b won't have been populated yet as that line hasn't been executed. Another press of 'n' will execute that line, but will then also move outside the if loop and b will now be out of scope. Is there a way to execute the current line without moving on so that its result can be inspected before it goes out of scope?
Another press of 'n' will execute that line, but will then also move
outside the if loop and b will now be out of scope
The problem is that next executes too much instructions and b variable becomes unavailable. You can substitute this single next with a number of step and finish commands to achieve more granularity in debugging and stop immediately after b was constructed. Here is sample gdb session for test program:
[ks#localhost ~]$ cat ttt.cpp
#include <string>
int main()
{
if (true)
{
std::string a = "aaa";
std::string b = "bbb";
}
return 0;
}
[ks#localhost ~]$ gdb -q a.out
Reading symbols from a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x40081f: file ttt.cpp, line 7.
Starting program: /home/ks/a.out
Temporary breakpoint 1, main () at ttt.cpp:7
7 std::string a = "aaa";
(gdb) n
8 std::string b = "bbb";
(gdb) p b
$1 = ""
(gdb) s
std::allocator<char>::allocator (this=0x7fffffffde8f) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/allocator.h:113
113 allocator() throw() { }
(gdb) fin
Run till exit from #0 std::allocator<char>::allocator (this=0x7fffffffde8f) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/allocator.h:113
0x0000000000400858 in main () at ttt.cpp:8
8 std::string b = "bbb";
(gdb) s
std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (this=0x7fffffffde70, __s=0x400984 "bbb", __a=...) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.tcc:656
656 basic_string<_CharT, _Traits, _Alloc>::
(gdb) fin
Run till exit from #0 std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (this=0x7fffffffde70, __s=0x400984 "bbb", __a=...) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.tcc:656
0x000000000040086d in main () at ttt.cpp:8
8 std::string b = "bbb";
(gdb) p b
$2 = "bbb"
Just add to the code b; the line afterwards. i.e.
if(something) {
string a = stringMaker();
string b = stringMaker();
b; // Break point here
}
Well you can always to a
(gdb) p stringMaker();
regardless of the line you're in given that stringMaker() is accessible. You can execute any kind statements , even involving variables if those variables are in current scope. For more advanced usage, you can use gdb's internal variables($1,$2 etc) to store certain result to use it later when the variables involved in that previous computation went out of scope.
Finally God(whatever that may be) send us gdb Python API. just type py and demolish your code to such extent that you will forget what you were doing at the first place.

How to print something without this format : $[num]=[value] in GDB environment?

What I want is this :
(gdb) define mynext
Redefine command "mynext"? (y or n) y
Type commands for definition of "mynext".
End with a line saying just "end".
>print "------"
>print Location:
>where
>print "-------------"
>print Code:
>list
>print "---------------------"
>print Next:
>next
>end
This is what outputs is:
$1 = "-----"
....
I expect:
-----
....
I used call printf("opopo") also, but It print the return value of "opopo" which is 5. Just like this:$4 = 5
My question is: how can I print something without this format which is :$[num]=[value].
As you found, print puts the printed value into the value history. gdb provides two different ways to avoid this.
One is printf. This works somewhat like the C function, but is a gdb command. Use it like:
(gdb) printf "whatever you like\n"
whatever you like
(gdb)
Another is output. This is a bit like the print command, but does not enter the value into the value history.
(gdb) output 5
5(gdb)
You can see from this that output also doesn't emit a trailing newline. You would have to add that yourself.

nested classes in GDB

In my C++ program I have a nested class defined as follows:
class A {
class B {
// ...
}
// ...
}
When I try casting a pointer in GDB like this: set $b = (A::B*)p
I get "A syntax error in expression"
I'm not familiar with the symbol (or debugging) information stored in the ELF files. I'm wondering what's wrong with my casting here and how to refer to a nested class in GDB.
The answer is to enclose the class name in single quotes:
set $b = ('A::B'*)p
See http://sourceware.org/bugzilla/show_bug.cgi?id=8693
Works for me (using current CVS GDB, as well as 7.3.1):
$ cat t.cc
struct A {
struct B {
int x;
};
int y;
};
int main()
{
A::B ab, *p = &ab;
return 0;
}
$ gcc -g t.cc && gdb -q ./a.out
(gdb) b main
Breakpoint 1 at 0x4005b8: file t.cc, line 10.
(gdb) r
Breakpoint 1, main () at t.cc:10
10 A::B ab, *p = &ab;
(gdb) p (A::B*)0x1
$1 = (A::B *) 0x1
(gdb) set $a = (A::B*)0x1
(gdb) p $a
$2 = (A::B *) 0x1
(gdb) quit

std::string::find_first_of does not return the expected value

I am trying to create an XML parser in C++. I am currently using cygwin and gcc to compile and gdb to debug. I have this piece of code:
const size_t mDataSize = mData.size();
...
size_t ltPos = mData.find_first_of('<', pos);
if (ltPos==mData.npos) {
...
mData is declared as private const std::string & within the class and holds the XML file content. After debugging with gdb I found the following:
(gdb) print pos
$12 = 636
(gdb) print mDataSize
$13 = 2692
(gdb) n
141 size_t ltPos = mData.find_first_of('<', pos);
(gdb) print ltPos
$14 = 114
(gdb) print pos
$15 = 636
(gdb) n
143 if (ltPos==mData.npos)
(gdb) print ltPos
$16 = 4294967295
(gdb) print mData[636]
$17 = (const char &) #0xb2b2a8: 10 '\n'
(gdb) print mData[637]
$18 = (const char &) #0xb2b2a9: 32 ' '
(gdb) print mData[638]
$19 = (const char &) #0xb2b2aa: 32 ' '
(gdb) print mData[639]
$20 = (const char &) #0xb2b2ab: 60 '<'
I was expecting 639 as result of calling find_first_of, but I am getting 4294967295 (which is -1 in a signed 32-bit int and matches std::string::npos). Can someone justify this behaviour? Or tell me how to workaround this?
So mData is declared as a reference? If so it doesn't really hold the content it holds a reference to the content. Is the thing to which mData refers still in existence at the time you're calling find_first_of?