GDB在c ++对象的构造函数中报告参数的错误地址

时间:2012-01-24 00:26:58

标签: c++ constructor gdb parameter-passing stdstring

我遇到了一个奇怪的行为,GDB将一个字符串作为参数传递给构造函数。 代码工作正常,但是当我在调试器中单步执行时,GDB似乎认为我的参数位于不同的地址。有谁知道这里发生了什么?

这是我可以创建的最简单的程序来演示问题:

--(jwcacces@neptune)--------------------------------------------(/home/jwcacces)--
--$ nl gdb_weird.cpp
     1  #include <iostream>
     2  #include <string>
     3
     4  class C
     5  {
     6  public:
     7     C(std::string str)
     8     {
     9        std::string* str_ptr = &str;
    10        std::cout << "Address of str: " << &str << std::endl;
    11        std::cout << "Address in str_ptr: " << str_ptr << std::endl;
    12        std::cout << "Value of str: " << str << std::endl;
    13     };
    14  };
    15
    16  int main(int, char*[])
    17  {
    18     std::string s("Hello, World!");
    19     C c(s);
    20     return 0;
    21  }

编译调试信息,无需优化 请注意,我在为x86,x64和mingw(x86)编译时看到了这个问题 我还没有尝试过其他架构。

--(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.

现在,调试:

--(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;

这是奇怪的,当我尝试输出str时,我得到垃圾:

(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>
                }
}

那么,GDB认为str的地址是什么?

(gdb) output &str
(std::string *) 0xffffd734

该计划认为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;

这真的很奇怪,程序认为str位于0xffffd748,但gdb认为它位于0xffffd734
并且,当您输出位于0xffffd748的字符串对象时,它可以正常工作。

(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!"
                }
}

程序本身使用参数没有问题:

(gdb) next
Value of str: Hello, World!
13         };

(gdb) continue
Continuing.
[Inferior 1 (process 19463) exited normally]

(gdb) quit

我尝试将构造函数参数的类型更改为int,struct,指针,但我无法重现这种怪异。
另外,我尝试将调试格式设置为-ggdb。

问题:

  • 这里发生了什么事?
  • 为什么gdb会说std::string的{​​{1}}成员已经过优化(可能是从库中优化出来的),这与它有什么关系吗?
  • 只是巧合,在GDB认为npos所在的“对象”中,str成员指向_M_p0xffffd748的地址实际上位于?
  • 在这种情况发生的其他情况下会发生什么?

---- WOAH,突破----
如果我将调试格式设置为-gstabs +,则GDB会将str的地址设置为正确 这是否意味着gdb调试格式无法正常工作?

1 个答案:

答案 0 :(得分:0)

在任何帖子(https://gcc.gnu.org/ml/gcc/2001-04/msg01037.html)中,调试C ++时,似乎-gstabs或-gstabs +是正确的标志。我希望这可以提供帮助。