I have a problem using gdb. I am using Eclipse-CDT as a frontend, but since this problem is obviously related to the gcc compiler or the gdb itself, I have reproduced it without Eclipse.
Sample Program
This small program should suffice to show my problem. I have saved this file as "main.cpp".
Expand|Select|Wrap|Line Numbers
- #include<vector>
- #include <iostream>
- struct I{
- std::vector<unsigned> p;
- I() : p(std::vector<unsigned>(1,0)){
- std::cout << "p has length " << p.size() << " and its first value is " << p[0] << std::endl;
- }
- };
- struct T{
- T (I i){
- std::cout << "i.p has length " << i.p.size() << " and its first value is " << i.p[0] << std::endl;
- }
- };
- int main(){
- I i;
- T t(i);
- }
Expand|Select|Wrap|Line Numbers
- g++ -O0 -g -o test main.cpp
Expand|Select|Wrap|Line Numbers
- p has length 1 and its first value is 0
- i.p has length 1 and its first value is 0
My problem is the debugging. Typing "gdb test" I started the following debugging session on the command line:
Expand|Select|Wrap|Line Numbers
- GNU gdb (GDB) 7.1-ubuntu
- Copyright (C) 2010 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 "i486-linux-gnu".
- For bug reporting instructions, please see:
- <http://www.gnu.org/software/gdb/bugs/>...
- Reading symbols from /home/jonathan/eclipse-workspace/test/test...done.
- (gdb) break main.cpp:19
- Breakpoint 1 at 0x80488ab: file main.cpp, line 19.
- (gdb) break main.cpp:13
- Breakpoint 2 at 0x8048a82: file main.cpp, line 13.
- (gdb) run
- Starting program: /home/jonathan/eclipse-workspace/test/test
- p has length 1 and its first value is 0
- Breakpoint 1, main () at main.cpp:19
- 19 T t(i);
- (gdb) print i
- $1 = {p = {<std::_Vector_base<unsigned int, std::allocator<unsigned int> >> = {
- _M_impl = {<std::allocator<unsigned int>> = {<__gnu_cxx::new_allocator<unsigned int>> = {<No data fields>}, <No data fields>}, _M_start = 0x804c008, _M_finish = 0x804c00c,
- _M_end_of_storage = 0x804c00c}}, <No data fields>}}
- (gdb) print {unsigned int}0x804c008
- $2 = 0
- (gdb) c
- Continuing.
- Breakpoint 2, T (this=0xbffff41f, i=...) at main.cpp:13
- 13 std::cout << "i.p has length " << i.p.size() << " and its first value is " << i.p[0] << std::endl;
- (gdb) print i
- $3 = {p = {<std::_Vector_base<unsigned int, std::allocator<unsigned int> >> = {
- _M_impl = {<std::allocator<unsigned int>> = {<__gnu_cxx::new_allocator<unsigned int>> = {<No data fields>}, <No data fields>}, _M_start = 0xbffff404, _M_finish = 0xbffff408,
- _M_end_of_storage = 0x80486d4}}, <No data fields>}}
- (gdb) print {unsigned int}0xbffff404
- $4 = 134529048
- (gdb) print {I}0xbffff404
- $5 = {p = {<std::_Vector_base<unsigned int, std::allocator<unsigned int> >> = {
- _M_impl = {<std::allocator<unsigned int>> = {<__gnu_cxx::new_allocator<unsigned int>> = {<No data fields>}, <No data fields>}, _M_start = 0x804c018, _M_finish = 0x804c01c,
- _M_end_of_storage = 0x804c01c}}, <No data fields>}}
- (gdb) print {unsigned int}0x804c018
- $6 = 0
- (gdb) c
- Continuing.
- i.p has length 1 and its first value is 0
- Program exited normally.
- (gdb) quit
First I set two breakpoints, namely at lines 19 and 13. Then I run the program (till before line 19) and let gdb print out the value of variable i. Its type is struct I, thus containing nothing but a std::vector<unsigned int> object, which itself contains three pointers to unsigned int: _M_start, _M_finish, and _M_end_of_storage. I want to know the value of the vector at index 0. I can view it by just dereferencing the _M_start pointer. I do this by printing the memory at adress 0x804c008 parsed as unsigned int. The value is 0, as I expected. Then I let the program run until the next breakpoint on line 13 and have gdb print out i and the memory at _M_start again. The value is 134529048, not 0, as it should be. Now I try dereferencing the alleged _M_start as a pointer to an object of struct I and find it to point to memory just looking like a well-structured I object, with a _M_start pointer to 0. I let my programm continue, it prints out information about i and then exits. I quit gdb.
What I can make of it
struct T's constructor T::T(I) in line 12 should get its argument i as a copy of the variable i in line 18. At least this is how I understand my code. But instead, variable i seems to be copied and then passed to the constructor by reference (technically, a pointer). This is neither call by reference nor call by value, as I understand it. The constructor seems to be able to cope with this, as the correct program output shows. However, the debugger interprets the reference to parameter i like the value of the parameter, which leads to the puzzling output following "print i". gdb's user sees a different i than the program sees.
What my problem is
For me this looks like some unwanted optimization done by the compiler. But I switched off any optimization (I used the -O0 flag). So is this a compiler bug? Or am I missing something here? Actually, I don't care that much about how the compiler handles my code, as long as my program does what it is supposed to (which is the case) and as long as the constructor T::T(I) gets hold of a copy of i, not of i itself (which seems to be the case, too). However, since I work on a project much more complex and I really depend on debugging, I want to view the variable's values and trust this information provided by the gdb. What can I do to make gdb's output reliable? And: Can anyone confirm this behaviour?
I would be delighed to find some help here. Of course and as always, I will be pleased to give more detail which could help solve this problem. Thanks in advance.
~<><~~~~~~~~ presencia