我遇到了 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调试格式不能正常工作?