【问题标题】:GDB's next command jumps backward to all stack-allocated objects at end of scopeGDB 的下一条命令向后跳转到作用域末尾的所有堆栈分配对象
【发布时间】:2018-09-17 02:41:52
【问题描述】:

当我在一个范围内有堆栈分配的对象(大括号内的一组命令),并且我在该范围的末尾使用next 时,gdb 会跳回到每个堆栈分配的对象所在的位置,以相反的顺序。

这在调试过程中令人不安:当有很多堆栈分配的对象实例时,调试器会向后跳转到每个实例,并且只有在完成后才会继续前进。相反,我希望它在范围之后继续到下一行。

有没有办法将 gdb 配置为不这样做,或者这是我在构建时需要传递给 gcc 的一些标志?

一开始我以为是我用-O0什么的(GDB jumps to wrong lines in out of order fashion)编译,但这里不是这样。

这是我的构建方式:

/opt/rh/devtoolset-6/root/usr/bin/c++  -MD -DDEBUG -g -ggdb -gstabs+  -fPIC  -Wall -Werror -Wsynth -Wno-comment -Wreturn-type   main.cpp -c -o main.o
/opt/rh/devtoolset-6/root/usr/bin/c++  -MD -DDEBUG -g -ggdb -gstabs+  -fPIC  -Wall -Werror -Wsynth -Wno-comment -Wreturn-type   main.o -L. -L/opt/rh/devtoolset-6/root/usr/lib64 -lstdc++  -o main.exe   

以下是我在调试器中看到的内容。注意所涉及的 GDB 版本:

bash-4.2$ gdb main.exe
GNU gdb (GDB) Red Hat Enterprise Linux 7.12.1-48.el6
Copyright (C) 2017 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-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from main.exe...done.
(gdb) b main
Breakpoint 1 at 0x400a27: file main.cpp, line 45.
(gdb) r
Starting program: /home/brentg/scratch_sandboxes/cxxminimal/main.exe 
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.192.el6.x86_64

Breakpoint 1, main (argc=1, argv=0x7fffffffeb38, envp=0x7fffffffeb48)
    at main.cpp:45
45    std::cout << __FILE__ << ":" << __LINE__ << ":" << "main begin" << std::endl;
Missing separate debuginfos, use: debuginfo-install libgcc-4.4.7-17.el6.x86_64 libstdc++-4.4.7-17.el6.x86_64
(gdb) l
40    std::cout << __FILE__ << ":" << __LINE__ << ":" << "printing some info 2" << std::endl;
41  }
42  
43  int main(int argc, char *argv[], char *const envp[])
44  {
45    std::cout << __FILE__ << ":" << __LINE__ << ":" << "main begin" << std::endl;
46    some_function_that_uses_Foo();
47    std::cout << __FILE__ << ":" << __LINE__ << ":" << "main end" << std::endl;
48    return 0;
49  } // end main
(gdb) n
main.cpp:45:main begin
46    some_function_that_uses_Foo();
(gdb) s
some_function_that_uses_Foo () at main.cpp:38
38    std::cout << __FILE__ << ":" << __LINE__ << ":" << "printing some info 1" << std::endl;
(gdb) n
main.cpp:38:printing some info 1
39    Foo the_foo1;
(gdb) n
40    std::cout << __FILE__ << ":" << __LINE__ << ":" << "printing some info 2" << std::endl;
(gdb) l
35  
36  void some_function_that_uses_Foo()
37  {
38    std::cout << __FILE__ << ":" << __LINE__ << ":" << "printing some info 1" << std::endl;
39    Foo the_foo1;
40    std::cout << __FILE__ << ":" << __LINE__ << ":" << "printing some info 2" << std::endl;
41  }
42  
43  int main(int argc, char *argv[], char *const envp[])
44  {
(gdb) n
main.cpp:40:printing some info 2
39    Foo the_foo1;

此时,我想知道:为什么我现在又回到了第 39 行?当我在第 40 行时,输入“next”,然后它似乎向后跳。

查看“下一个”命令的 gdb 手册,我没有看到任何关于 C++ 构造函数/析构函数的内容。

【问题讨论】:

  • 我遇到了你每天所说的“问题”,因为 gdb 会跳转到你本地对象的析构函数。我认为这是设计使然,在 gdb 邮件列表中有很多关于此的讨论。
  • @ollydbg23 谢谢。我搜索并找到了sourceware.org/ml/gdb/2011-10/msg00214.html,这意味着 GCC 有责任发出 GDB 可以用来确定在哪里停止的调试信息。这对我来说真的不是一个答案,但它可能有助于产生一个答案。
  • gcc.gnu.org/bugzilla/show_bug.cgi?id=49951#c21 是 2015 年 2 月 3 日 01:04:40 UTC 对该错误的最后评论。它仍然没有修复,现在已经进入 2018 年了。
  • 啊哈,那个名叫“asmwarrior”的评论者是我。我真的忘记这是一个 GDB 错误或 GCC 错误,希望我们可以“ping”这个错误报告,并且一些开发人员可以站出来解决这个问题。

标签: gcc gdb stack-frame


【解决方案1】:

/opt/rh/devtoolset-6/root/usr/bin/c++ -MD -DDEBUG -g -ggdb -gstabs+ ...

您可能正在遭受自伤。

STABS debugging format 是古老的,不应在任何 15 岁以下的系统上使用。它也完全不足并且完全未经测试。

libgcc-4.4.7-17.el6.x86_64

您还使用了 2012 年 3 月发布的古老 GCC-4.4.7。使用更现代的版本您可能会获得更好的调试体验。

【讨论】:

  • 首先,这是个好建议,不要使用刺。其次,这种步进行为也会发生在 DWARF 中,因为 gcc 告诉 gdb 进入析构函数。我认为没有标志可以禁用此功能。也许你可以使用skip 命令。
  • 经过进一步研究,我得出结论,这是一个尚未修复的错误。请参阅stackoverflow.com/questions/52360140/… 处的评论
  • 我回去检查了我正在使用的 GCC 的实际版本,它显示“c++ (GCC) 6.2.1 20160916 (Red Hat 6.2.1-3)”,而不是“古代GCC-4.4.7" 版本,如本答案所示。
  • 另外,我尝试使用使用上述 GCC 6.2.1 编译器的构建,但使用 -gsplit-dwarf 选项 (gcc.gnu.org/wiki/DebugFission),它表现出同样的问题。
猜你喜欢
  • 1970-01-01
  • 2017-10-22
  • 2013-10-25
  • 2011-12-04
  • 2015-08-30
  • 2013-01-25
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多