我希望gdb只显示我的代码(跳过包含的标题)。我正在与多线程程序随机抛出的分段错误作斗争。在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
错误发生在我的代码(不在线程库中)的什么时候?或者至少是哪个对线程::joinable()函数的调用导致了错误?有可能得到这样的信息吗?我很抱歉问这样的问题,但我对gdb调试完全陌生。
最里面的(活动的)堆栈帧是帧#0,调用方是帧#1等等。从上到下看,我注意到帧#0在名称空间std
内的一个函数中,并引用系统头文件作为源代码,但帧#1已经在一个名为Finder
的类中提到了一个方法,该方法不是由标准库提供的,并且源代码路径也不涉及系统报头。此外,快速谷歌不会产生表明Finder
类是众所周知的框架的一部分的结果,因此它很可能是您的代码。
Finder::join_threads
在global_search.cpp第25行的std::线程指针nullptr
(也称为NULL
)上调用joinable。
这里有两种情况。
有一个案例——您的问题中的案例——涉及堆栈跟踪。在这种情况下,根本无法消除来自程序外部的帧。我想gdb可以被教导以某种方式做到这一点,比如使用帧过滤器,但在实践中会令人困惑,因为调试器会呈现出你正在调试的程序的当前状态的伪造视图。
对于这种情况,我通常只使用"向上"命令在堆栈中向上走,直到我看到我感兴趣的东西
另一种情况是踩踏。在这种情况下,gdb提供了"skip"命令,该命令指示它不要单步执行某些代码位。这对于省略访问者和外来代码非常方便。请注意,这与从堆栈跟踪中删除信息没有相同的问题,因为gdb没有伪造任何信息,它只是将"步骤"one_answers"下一步"视为较长操作的简写。