【问题标题】:How to have gdb exit if program succeeds, break if program crashes?如果程序成功如何让gdb退出,如果程序崩溃则中断?
【发布时间】:2012-01-29 06:26:53
【问题描述】:

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

【问题讨论】:

    标签: gdb


    【解决方案1】:

    最简单的方法是使用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 文件注册事件处理程序。

    【讨论】:

    【解决方案2】:

    这有点老套,但你可以这样做:

    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;
    }
    

    【讨论】:

    • 我在 OS X Snow Leopard 上,这里的 gdb 不支持 --eval-command,但无论如何我会选择你的答案。
    • 我认为如果您的set confirm off 文件中有set confirm off,这将不起作用,GDB 将始终返回...
    • gdb --eval-command=run --eval-command="set confirm off" --eval-command=bt --eval-command=quit --args ./a.out
    【解决方案3】:

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

    python
    
    def exit_handler ( event ):
      if event .exit_code == 0:
        gdb .execute ( "quit" )
    
    gdb .events .exited .connect ( exit_handler )
    
    end
    

    以上是凯文的回答的改进。

    【讨论】:

      【解决方案4】:

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

      run
      quit
      

      不带选项运行:

      gdb --args prog arg1...
      

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

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

        • 这不是这个特定问题的最佳答案,但它对我的问题帮助很大!谢谢,不知道-return-child-result
        【解决方案6】:

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

        您更有可能想要使用 Valgrind。

        【讨论】:

          【解决方案7】:

          让它崩溃时转储核心。如果您使用的是 linux,请阅读 man core 手册页以及运行 bashulimit 内置函数。

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

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

          【讨论】:

            猜你喜欢
            • 2018-05-19
            • 2014-10-27
            • 2012-10-18
            • 1970-01-01
            • 1970-01-01
            • 2012-03-09
            • 1970-01-01
            • 2021-12-08
            • 1970-01-01
            相关资源
            最近更新 更多