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

时间:2021-07-21 14:30:02

I am attempting to capture failed asserts in my program. I’m using a library that makes direct calls to assert(), rather than a custom function or macro, and it is within this library I am currently trying to trace several porting-related bugs. Everything involved has been compiled with debug symbols in g++.

我试图在我的程序中捕获失败的断言。我正在使用一个直接调用assert()的库,而不是自定义函数或宏,并且它在此库中我正在尝试跟踪几个与移植相关的错误。涉及的所有内容都使用g ++中的调试符号进行编译。

The best solution I have found is breaking at the file:line of the assert, with the condition of the assert expression. This allows stopping on the assert before it fails, but is a horrible solution. It requires special setup for each possibly-failing assert, won’t work from my IDE, and is far too much effort in general.

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

How can I break on any failed assert using gdb & gcc in such a way that allows examination of the callstack and variables within the scope of the assert call?

如何以允许检查assert调用范围内的callstack和变量的方式使用gdb和gcc中断任何失败的断言?

It would be even better if the solution allowed me to discard the assert's failure and continue running.

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

3 个解决方案

#1


19  

Setting a breakpoint on abort() seems to be the best answer.

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

break abort in gdb's CLI.

在gdb的CLI中断中止。

#2


3  

No break is needed on Linux, just type bt on the prompt

Linux上不需要中断,只需在提示符下键入bt即可

abort() causes a signal to be raised on Linux, and GDB already breaks on signals by default.

abort()导致在Linux上引发信号,并且GDB默认已经中断了信号。

E.g.:

#include <assert.h>

void g(int i) {
    assert(0);
}

void f(int i) {
    g(i);
}

int main(void) {
    f(1);
}

Then:

gcc -std=c99 -O0 -ggdb3 -o a a.c
gdb -ex run ./a

Then just type bt in the shell:

然后在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

Which already shows the function values (f (i=1)).

其中已经显示了函数值(f(i = 1))。

And you can also do as usual:

你也可以照常做:

(gdb) f 4
#4  0x00005555555546ca in g (i=1) at a.c:4
4           assert(0);
(gdb) p i
$1 = 1

Tested in Ubuntu 16.10, gdb 7.11.

在Ubuntu 16.10中测试,gdb 7.11。

#3


1  

If suggested above answers doesn't work for you, you may try to break on __assert_fail function.

如果建议上面的答案对你不起作用,你可以尝试打破__assert_fail函数。

break __assert_fail

Name is most probably implementation - dependent, but it's easy to find if you look at definition of assert macro on your platform. This will allow you to break before SIGABRT.

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

#1


19  

Setting a breakpoint on abort() seems to be the best answer.

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

break abort in gdb's CLI.

在gdb的CLI中断中止。

#2


3  

No break is needed on Linux, just type bt on the prompt

Linux上不需要中断,只需在提示符下键入bt即可

abort() causes a signal to be raised on Linux, and GDB already breaks on signals by default.

abort()导致在Linux上引发信号,并且GDB默认已经中断了信号。

E.g.:

#include <assert.h>

void g(int i) {
    assert(0);
}

void f(int i) {
    g(i);
}

int main(void) {
    f(1);
}

Then:

gcc -std=c99 -O0 -ggdb3 -o a a.c
gdb -ex run ./a

Then just type bt in the shell:

然后在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

Which already shows the function values (f (i=1)).

其中已经显示了函数值(f(i = 1))。

And you can also do as usual:

你也可以照常做:

(gdb) f 4
#4  0x00005555555546ca in g (i=1) at a.c:4
4           assert(0);
(gdb) p i
$1 = 1

Tested in Ubuntu 16.10, gdb 7.11.

在Ubuntu 16.10中测试,gdb 7.11。

#3


1  

If suggested above answers doesn't work for you, you may try to break on __assert_fail function.

如果建议上面的答案对你不起作用,你可以尝试打破__assert_fail函数。

break __assert_fail

Name is most probably implementation - dependent, but it's easy to find if you look at definition of assert macro on your platform. This will allow you to break before SIGABRT.

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