I experience strange behavior with GDB, passing a string as a parameter to the constructor. The code works fine, but when I go into the debugger, GDB seems to think that my parameter is on a different address than it is. Does anyone know what is going on here?
Here is the simplest program I can create that demonstrates the problem:
--( jwcacces@neptune )--------------------------------------------(/home/jwcacces)-- --$ nl gdb_weird.cpp 1
Compile with debugging information, without optimization.
Please note that I see this problem when compiling for x86, x64 and mingw (x86).
I have not tried other architectures.
--( jwcacces@neptune )--------------------------------------------(/home/jwcacces)-- --$ g++ -O0 -g -Wall -Wextra gdb_weird.cpp -m32 --( jwcacces@neptune )--------------------------------------------(/home/jwcacces)-- --$ g++ --version g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 Copyright (C) 2011 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Now debugging:
--( jwcacces@neptune )--------------------------------------------(/home/jwcacces)-- --$ gdb a.out GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". For bug reporting instructions, please see: <http://bugs.launchpad.net/gdb-linaro/>... Reading symbols from /home/jwcacces/a.out...done. (gdb) br main Breakpoint 1 at 0x80488ce: file gdb_weird.cpp, line 18. (gdb) run Starting program: /home/jwcacces/a.out Breakpoint 1, main () at gdb_weird.cpp:18 18 std::string s("Hello, World!"); (gdb) next 19 C c(s); (gdb) step C::C (this=0xffffd74f, str=...) at gdb_weird.cpp:9 9 std::string* str_ptr = &str;
Here's the weird thing when I try to print str , I get garbage:
(gdb) output str { static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xffffd748 "\024\260\004\b\364\177\354\367\360\211\004\b\364\177\354", <incomplete sequence \367> } }
So what does GDB think, is there an str address?
(gdb) output &str (std::string *) 0xffffd734
And what does the program think, address str ?
(gdb) next 10 std::cout << "Address of str: " << &str << std::endl; (gdb) next Address of str: 0xffffd748 11 std::cout << "Address in str_ptr: " << str_ptr << std::endl; (gdb) next Address in str_ptr: 0xffffd748 12 std::cout << "Value of str: " << str << std::endl;
This is really strange, the program thinks str is at 0xffffd748 , but gdb thinks its at 0xffffd734
And when you output the string object, which will be at 0xffffd748 , it will work correctly.
(gdb) output *(std::string*)0xffffd748 { static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields> }, _M_p = 0x804b014 "Hello, World!" } }
And the hs program itself has no problem using the parameter:
(gdb) next Value of str: Hello, World! 13 }; (gdb) continue Continuing. [Inferior 1 (process 19463) exited normally] (gdb) quit
I tried changing the type of the constructor parameter to int, struct, pointer, but I can't reproduce the weirdness.
In addition, I tried setting the debug format to -ggdb.
Questions:
- What's going on here?
- Why does gdb say that the
std::string npos optimized (possibly optimized from the library), and does this have anything to do with it? - Is it just a coincidence that in the “object” where GDB thinks
str is there, the _M_p member points to 0xffffd748 , the address that str is actually in? - In what cases do such circumstances occur?
---- WOAH, Breakthrough ----
If I set the debug format to -gstabs +, GDB will get the str address on the right.
Does this mean that the gdb debugging format is not working correctly?