C++ 在gdb中中断失败的断言的正确方法是什么?

C++ 在gdb中中断失败的断言的正确方法是什么?,c++,debugging,gdb,g++,assert,C++,Debugging,Gdb,G++,Assert,我试图在程序中捕获失败的断言。我正在使用一个直接调用assert()的库,而不是一个自定义函数或宏,我目前正试图在这个库中跟踪几个与移植相关的bug。所涉及的一切都是用g++中的调试符号编译的 我找到的最好的解决方案是在文件处断开:断言行,以及断言表达式的条件。这允许在断言失败之前停止断言,但这是一个可怕的解决方案。它需要为每个可能失败的断言进行特殊设置,在我的IDE中无法工作,并且通常需要付出太多的努力 如何使用gdb和gcc中断任何失败的断言,从而允许检查断言调用范围内的调用堆栈和变量? 如

我试图在程序中捕获失败的断言。我正在使用一个直接调用assert()的库,而不是一个自定义函数或宏,我目前正试图在这个库中跟踪几个与移植相关的bug。所涉及的一切都是用g++中的调试符号编译的

我找到的最好的解决方案是在文件处断开:断言行,以及断言表达式的条件。这允许在断言失败之前停止断言,但这是一个可怕的解决方案。它需要为每个可能失败的断言进行特殊设置,在我的IDE中无法工作,并且通常需要付出太多的努力

如何使用gdb和gcc中断任何失败的断言,从而允许检查断言调用范围内的调用堆栈和变量?


如果解决方案允许我放弃断言失败并继续运行,那就更好了。

abort()
上设置断点似乎是最好的答案


在gdb的CLI中,
break abort

Linux上不需要
break
,只需在提示符下键入
bt

abort()。例如:

a、 c

然后在shell中键入
bt

(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:58
#1  0x00007ffff7a483ea in __GI_abort () at abort.c:89
#2  0x00007ffff7a3ebb7 in __assert_fail_base (fmt=<optimized out>, assertion=assertion@entry=0x555555554788 "0", file=file@entry=0x555555554784 "a.c", line=line@entry=4, 
    function=function@entry=0x55555555478a <__PRETTY_FUNCTION__.1772> "g") at assert.c:92
#3  0x00007ffff7a3ec62 in __GI___assert_fail (assertion=0x555555554788 "0", file=0x555555554784 "a.c", line=4, function=0x55555555478a <__PRETTY_FUNCTION__.1772> "g")
    at assert.c:101
#4  0x00005555555546ca in g (i=1) at a.c:4
#5  0x00005555555546df in f (i=1) at a.c:8
#6  0x00005555555546f0 in main () at a.c:12
控制GDB是否默认断开信号的设置为:
handleall nostop
,如所示:


在Ubuntu 16.10、gdb 7.11中测试。

如果以上建议的答案对您不起作用,您可以尝试使用“断言”失败功能

break __assert_fail

名称很可能依赖于实现,但若您查看平台上assert宏的定义,就很容易找到它。这将允许您在SIGABRT之前中断。

在Visual Studio中的Windows上,中断是失败的
断言的默认行为。我感到惊讶的是,在*nix世界中情况并非如此-失败的
断言在那里通常做什么?在gdb中,在程序运行之前,您可以使用
中断中止
(或者只使用
中断
)在函数abort()处添加断点。这至少可以让您在断言失败时进行回溯(假设断言失败时调用
abort()
;某些实现可能会调用
exit()
)。但不确定是否继续执行。通常这在默认情况下有效,因为assert()调用abort,abort发出SIGABRT信号,而gdb在默认情况下在该信号上中断,允许您检查堆栈,上/下移动堆栈,例如,移动到包含assert()的函数和检查变量等等。@notmyfriend在我的实现中,似乎,在失败的断言/中止时中断不是默认的;可能是因为这是一个MSYS2 MinGW设置,尽管我可以发誓这在Linux上发生过一次。在任何情况下,
break abort
似乎都能工作,而且在我的IDE中也能工作。如果你想把它格式化成一个答案,我会接受它。@WilliamKappler似乎你应该自己写答案,自己接受它-我相信你可以得到某种徽章。;-。我对MinGW提出了同样的问题。最初的海报和@notmyfriend都在他们的评论中发布了答案,但是在建议某人写一个正式的答案,并且每次我忘了的时候都会回到这个页面几次,然后不得不重新阅读所有的评论来找出答案是什么之后,我就写下来了!这真是天才!注意:在某些平台上(例如,某些Windows Shell下的MinGW),gdb看不到SIGABRT信号,因此程序只是在assert上死掉,没有停止gdb,但在abort上设置断点仍然有效。一个值得注意的例外是在GTest中运行测试,因此在调试测试时,您可能仍然希望在
abort
上设置断点。
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:58
#1  0x00007ffff7a483ea in __GI_abort () at abort.c:89
#2  0x00007ffff7a3ebb7 in __assert_fail_base (fmt=<optimized out>, assertion=assertion@entry=0x555555554788 "0", file=file@entry=0x555555554784 "a.c", line=line@entry=4, 
    function=function@entry=0x55555555478a <__PRETTY_FUNCTION__.1772> "g") at assert.c:92
#3  0x00007ffff7a3ec62 in __GI___assert_fail (assertion=0x555555554788 "0", file=0x555555554784 "a.c", line=4, function=0x55555555478a <__PRETTY_FUNCTION__.1772> "g")
    at assert.c:101
#4  0x00005555555546ca in g (i=1) at a.c:4
#5  0x00005555555546df in f (i=1) at a.c:8
#6  0x00005555555546f0 in main () at a.c:12
(gdb) f 4
#4  0x00005555555546ca in g (i=1) at a.c:4
4           assert(0);
(gdb) p i
$1 = 1
break __assert_fail