我使用assert
中的<cassert>
来检查多线程C ++ 11程序中的不变量。当断言失败时,我希望能够在失败的断言时检查失败函数的状态,以及仍然完整的回溯,变量状态等。问题似乎是SIGABRT
和我的线程之间的一些交互,因为我的std::thread
是pthread_kill
,可能是由某个默认信号处理程序。如何在断言失败时暂停gdb?
以下是我尝试过的一些事情:
在SIGABRT
上设置一个抓点。这种情况确实发生了,但为时已晚(__pthread_kill
)。
定义__assert_fail
,即extern
中声明的<assert.h>
,并在其上设置gdb断点。这从来没有被捕获,所以假设pthread在被调用之前被杀死了(?)。
这里推荐的方法是什么?
答案 0 :(得分:4)
我做了以下事情:
示例程序:
#include <cassert>
void f2()
{
assert(0);
}
void f1()
{
f2();
}
int main()
{
f1();
}
现在我设置了一个断点到f2,希望我可以在stepi
之后逐步使用断言:
gdb > break f2
gdb > run
Breakpoint 11, f2 () at main.cpp:5
gdb > stepi // several times!!!!
0x080484b0 in __assert_fail@plt ()
唉唉!我们可以看到stepi
转到符号,告诉我们有一个具有该名称的函数。因此,只设置__assert_fail@plt
gdb > break __assert_fail@plt
gdb > run
Breakpoint 11, f2 () at main.cpp:5
(gdb) bt
#0 0x080484b0 in __assert_fail@plt ()
#1 0x080485f7 in f2 () at main.cpp:5
#2 0x08048602 in f1 () at main.cpp:10
#3 0x0804861b in main () at main.cpp:15
适合我!
答案 1 :(得分:0)
如果由于某种原因你需要断言断言,Klaus对__assert_fail
中断的回答是绝对正确的。
然而,事实证明,设置断点以在多线程程序中查看gdb中的堆栈跟踪根本就没有必要,因为gdb已经在SIGABRT
中断并切换了中止线程。在我的情况下,我有一个错误配置的库,导致这个红鲱鱼。如果您尝试使用多线程程序在gdb中查看来自中止代码(SIGABRT
)的堆栈跟踪,则无需在gdb中执行任何操作(假设已使用默认信号处理程序)。
仅供参考,您可以通过运行info signals
来查看默认信号处理程序,并通过运行SIGABRT
来查看info signals SIGABRT
相同的信号处理程序。在我的机器上,我看到了这一点,显示该程序将被停止,等等。如果由于某种原因,SIGABRT
信号处理程序未设置为在SIGABRT
停止,则需要更改该设置。有关详情,请访问https://sourceware.org/gdb/onlinedocs/gdb/Signals.html。
(gdb) info signals SIGABRT
Signal Stop Print Pass to program Description
SIGABRT Yes Yes Yes Aborted