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

2024-01-01

我遇到了 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 is?

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

程序认为地址是什么str is?

(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 is at 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's npos成员被优化了(可能是从库中优化了),这有什么关系吗?
  • 在“对象”中,GDB认为这只是一个巧合吗?str是个_M_p成员指向0xffffd748,地址str实际上位于?
  • 在其他什么情况下会出现这种行为?

---- 哇哦,突破 ----
如果我将调试格式设置为-gstabs+,GDB将获取地址str right.
这是否意味着gdb调试格式不能正常工作?


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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GDB 报告 c++ 对象构造函数中参数的地址错误 的相关文章

随机推荐