GDB 报告 c++ 中参数的地址错误对象的构造函数
我遇到了 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 的 npos 成员已优化(可能是从库中优化),这与它有什么关系吗?
- 这只是巧合吗,在 GDB 认为
str
所在的“对象”中,_M_p
成员指向0xffffd748
地址str
实际上位于? - 在其他什么情况下会出现这种行为?
---- 哇,突破 ----
如果我将调试格式设置为 -gstabs+,GDB 会正确获取 str
的地址。
这是否意味着gdb调试格式不能正常工作?
I'm experiencing a weird behavior with GDB passing a string as the parameter to a constructor.
The code works fine, but when I step through in the debugger, GDB seems to think my parameter is at a different address then it is. Does anyone know what's going on here?
Here's the simplest program I can create that demonstrates the problem:
--(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 }
Compile with debugging info, no optimization.
Note, that I see this problem when compiled 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, debug:
--(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 weirdness, when I try to output 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 the address of str
is?
(gdb) output &str
(std::string *) 0xffffd734
And what does the program think the address of 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;
This is really strange, the program thinks str
is at 0xffffd748
, but gdb thinks its at 0xffffd734
And, when you output the string object that would be at 0xffffd748
it works 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 program itself hs 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 have tried changing the type of the constructor parameter to an int, a struct, a pointer, but I can not reproduce the weirdness.
Also, I have tried setting the debugging format to -ggdb.
Questions:
- What's going on here?
- Why does gdb say that
std::string
'snpos
member is optimized out (optimized out of library maybe), and does that have anything to do with it? - Is it just a coincidence that in the "object" that would be where GDB thinks
str
is, the_M_p
member points to0xffffd748
, the address thatstr
actually is located at? - In what other circumstances with this behavior happen?
---- WOAH, Breakthrough ----
If I set the debugging format to -gstabs+, GDB gets the address of str
right.
Does this mean that the gdb debugging format does not work correctly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
来自任何帖子(https://gcc.gnu.org/ml/gcc /2001-04/msg01037.html)在调试 C++ 时,-gstabs 或 -gstabs+ 似乎是正确的标志。我希望这能有所帮助。
From any post (https://gcc.gnu.org/ml/gcc/2001-04/msg01037.html) it seems that -gstabs or -gstabs+ are the correct flags when debugging C++. I hope this can help.