如何让gdb在程序成功时退出,在程序崩溃时中断?

问题描述 投票:0回答:7

我的代码中似乎存在某种多线程错误,导致每运行 30 次测试套件就会崩溃。该测试套件是非交互式的。我想在 gdb 中运行我的测试套件,如果程序正常退出,则让 gdb 正常退出;如果程序崩溃,则中断(并显示调试提示)。这样我就可以让测试套件重复运行,去喝杯咖啡,回来后就会看到一个很好的调试提示。我怎样才能用 gdb 做到这一点?

gdb
7个回答
37
投票

这有点hacky,但你可以这样做:

gdb -ex='set confirm on' -ex=run -ex=quit --args ./a.out

如果 a.out 正常终止,它只会让你退出 GDB。但如果你崩溃了,程序仍然会处于活动状态,因此 GDB 通常会提示你是否确实想以活动的下级退出:

Program received signal SIGABRT, Aborted.
0x00007ffff72dad05 in raise (sig=...) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64  ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
    in ../nptl/sysdeps/unix/sysv/linux/raise.c
A debugging session is active.

    Inferior 1 [process 15126] will be killed.

Quit anyway? (y or n) 

就像我说的,不太漂亮,但只要您没有关闭退出活动进程的提示,它就可以工作。可能还有一种方法可以使用 gdb 的

quit
命令:它需要一个数字参数,该参数是调试会话的退出代码。所以也许你可以使用 --eval-command="quit stuff",其中 stuff 是一些 GDB 表达式,反映下级是否正在运行。

这个程序可以用来测试一下:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    if (time(NULL) % 2) {
        raise(SIGINT);
    }
    puts("no crash");
    return EXIT_SUCCESS;
}

9
投票

最简单的方法是使用gdb提供的

Python API

 def exit_handler(event):
     gdb.execute("quit")
 
 gdb.events.exited.connect(exit_handler)

您甚至可以用一行代码完成:

(gdb) python gdb.events.exited.connect(lambda x : gdb.execute("quit"))

您还可以检查返回代码,以确保它是您期望的“正常”代码

event.exit_code

您可以将其与 @acm 提到的

--eval-command
--command
结合使用,从命令行或使用
.gdbinit
文件注册事件处理程序。


8
投票

也可以在程序崩溃时触发回溯,让gdb带着子进程的返回码退出:

gdb -return-child-result -ex run -ex "thread apply all bt" -ex "quit" --args myProgram -myProgramArg

3
投票

创建一个名为

.gdbinit
的文件,启动 gdb 时将使用该文件。

run
quit

不带任何选项运行:

gdb --args prog arg1...

您告诉 gdb 运行并退出,但如果发生错误,它应该停止处理文件。


2
投票

让它在崩溃时转储核心。如果您使用的是 Linux,请阅读

man core
手册页,如果您正在运行
ulimit
,请阅读
bash
内置函数。

这样,当它崩溃时,你会找到一个不错的核心文件,可以将其提供给 gdb:

$ ulimit -c unlimited
$ ... run program ..., gopher coffee (or reddit ;)
$ gdb progname corefile

2
投票

如果您将以下几行放入

~/.gdbinit
文件中,则当您的程序以状态代码 0 退出时,
gdb
将会退出。

python

def exit_handler ( event ):
  if event .exit_code == 0:
    gdb .execute ( "quit" )

gdb .events .exited .connect ( exit_handler )

end

以上是Kevin答案的精炼。


-2
投票

崩溃时没有获取到核心文件吗?像这样“gdb -c core”启动 gdb 并进行堆栈回溯。

您更有可能想要使用 Valgrind。

© www.soinside.com 2019 - 2024. All rights reserved.