如何正确使用gdb?

How to properly use gdb?

我希望 gdb 只显示我的代码(跳过包含的 headers)。我正在为我的多线程程序随机抛出的分段错误而苦苦挣扎。在 gdb 中我可以看到这个:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffeffff700 (LWP 27533)]
0x0000000000409939 in std::thread::joinable (this=0x0) at /usr/include/c++/4.9.2/thread:162
162     { return !(_M_id == id()); }
(gdb) bt
#0  0x0000000000409939 in std::thread::joinable (this=0x0) at /usr/include/c++/4.9.2/thread:162
#1  0x0000000000404562 in Finder::join_threads (this=0x7ffff0000cd0) at global_search.cpp:25
#2  0x0000000000416ea9 in std::_Mem_fn<void (Finder::*)()>::operator()<, void>(Finder&) const (this=0x7ffff00013c0, __object=...) at /usr/include/c++/4.9.2/functional:556
#3  0x0000000000416d1e in std::_Mem_fn<void (Finder::*)()>::operator()<Finder<>, void>(std::reference_wrapper<Finder<> >, (void&&)...) const (this=0x7ffff00013c0, __ref=...)
    at /usr/include/c++/4.9.2/functional:585
#4  0x00000000004166fe in std::_Bind_simple<std::_Mem_fn<void (Finder::*)()> (std::reference_wrapper<Finder>)>::_M_invoke<0ul>(std::_Index_tuple<0ul>) (this=0x7ffff00013b8)
    at /usr/include/c++/4.9.2/functional:1700
#5  0x00000000004160eb in std::_Bind_simple<std::_Mem_fn<void (Finder::*)()> (std::reference_wrapper<Finder>)>::operator()() (this=0x7ffff00013b8)
    at /usr/include/c++/4.9.2/functional:1688
#6  0x0000000000415b12 in std::thread::_Impl<std::_Bind_simple<std::_Mem_fn<void (Finder::*)()> (std::reference_wrapper<Finder>)> >::_M_run() (this=0x7ffff00013a0)
    at /usr/include/c++/4.9.2/thread:115
#7  0x00007ffff76b4d90 in execute_native_thread_routine () from /usr/lib/libstdc++.so.6
#8  0x00007ffff7910374 in start_thread () from /usr/lib/libpthread.so.0
#9  0x00007ffff6e2427d in clone () from /usr/lib/libc.so.6

在我的代码中(不是在线程库中)什么时候发生了错误?或者至少是对 thread::joinable() 函数的哪个调用导致了错误?有可能得到这样的信息吗?很抱歉提出这样的问题,但我对使用 gdb 进行调试完全陌生。

这里有两种情况。

一个案例——您问题中的那个——涉及堆栈跟踪。在这种情况下,没有办法消除来自程序外部的帧。我想可以教 gdb 以某种方式做到这一点,比如使用帧过滤器,但在实践中会造成混淆,因为调试器随后会呈现您正在调试的程序的当前状态的伪造视图。

对于这种情况,我通常只使用 "up" 命令在堆栈中向上走,直到看到我感兴趣的内容。

另一种情况是步进。对于这种情况,gdb 提供了 "skip" 命令,指示它不要单步执行某些代码位。这可以方便地省略访问器和外部代码。请注意,这不会出现与从堆栈跟踪中删除信息相同的问题,因为 gdb 不会伪造任何信息,它只是将 "step" 和 "next" 视为 shorthand 更长时间操作。

最里面的(活动的)栈帧是帧 #0,调用方帧 #1 等等。从上到下看,我注意到第 0 帧在命名空间 std 内的一个函数中,并引用系统头文件作为源代码,但第 1 帧已经提到 class 中的一个方法Finder,标准库没有提供,源代码路径也没有引用系统头文件。此外,快速 google 不会产生表明 Finder class 是知名框架的一部分的结果,因此很可能是您的代码。

Finder::join_threads 在 global_search.cpp.

的第 25 行中的 std::thread 指针上调用 joinable,该指针是 nullptr(又名 NULL