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

时间:2011-12-28 15:17:44

标签: gdb

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

7 个答案:

答案 0 :(得分:21)

这有点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”,其中的东西是一些反映下级是否正在运行的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;
}

答案 1 :(得分:8)

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

 def exit_handler(event):
     gdb.execute("quit")

 gdb.events.exited.connect(exit_handler)

您甚至可以使用一行:

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

您还可以检查返回代码,以确保它是event.exit_code所需的“正常”代码。

您可以将其与@acm所提及的--eval-command--command结合使用,以从命令行或.gdbinit文件注册事件处理程序。

答案 2 :(得分:4)

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

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

答案 3 :(得分:3)

创建一个名为.gdbinit的文件,它将在gdb启动时使用。

run
quit

无选项运行:

gdb --args prog arg1...

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

答案 4 :(得分:2)

崩溃时使其转储核心。如果您使用的是Linux,请阅读man core手册页,如果您正在运行ulimit,请阅读内置bash

这种方式崩溃时你会找到一个可以提供给gdb的好的核心文件:

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

答案 5 :(得分:1)

如果您在~/.gdbinit文件中添加以下行,则当您的程序以状态代码0退出时,gdb将退出。

python

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

gdb .events .exited .connect ( exit_handler )

end

以上是凯文答案的改进。

答案 6 :(得分:-2)

崩溃时你没有收到核心文件吗?像这个'gdb -c core'一样启动gdb并进行堆栈回溯。

你更有可能想要使用Valgrind。