关于调试:分段错误的行号

Line number of segmentation fault

我可以设置任何gcc选项来给出分段错误的行号吗?

我知道我可以:

  • 逐行调试
  • 把printfs放在代码中缩小范围。
  • 编辑:

  • gdb上的bt/where不给出堆栈。
  • 有益的建议

  • 我不知道gcc选项,但是您应该能够使用gdb运行应用程序,然后当它崩溃时,键入where在堆栈退出时查看它,这会使您接近。

    1
    2
    3
    $ gdb blah
    (gdb) run
    (gdb) where

    编辑完整性:

    您还应该确保使用-ggcc选项在上构建带有调试标志的应用程序,以便在可执行文件中包含行号。

    另一种选择是使用bt命令(backtrace)。


    这是一个完整的shell/gdb会话

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ gcc -ggdb myproj.c
    $ gdb a.out
    gdb> run --some-option=foo --other-option=bar
    (gdb will say your program hit a segfault)
    gdb> bt
    (gdb prints a stack trace)
    gdb> q
    [are you sure, your program is still running]? y
    $ emacs myproj.c # heh, I know what the error is now...

    愉快的黑客攻击:—)


    当程序得到一个SEGV信号时,您可以让GCC打印一个StActTrace,类似于Java和其他友好语言如何处理空指针异常。有关详细信息,请参阅我的回答:

    • 如何在我的C++应用程序崩溃时生成堆栈(使用GCC编译器)

    这方面的好处是,您可以将它留在代码中;您不需要通过gdb运行东西来获得好的调试输出。

    如果使用-g进行编译并遵循其中的说明,则可以使用命令行工具(如addr2line)从输出中获取文件/行信息。


    在Valgrind下运行。


    如果使用调试(-g)编译并在调试器(gdb、run、bt)下运行的所有上述建议都不适用于您,则:

    • 初级:也许你没有在调试器下运行,你只是在分析死后核心转储。(如果您启动调试会话,但不运行该程序,或者如果它退出,那么当您请求回溯时,gdb将说"无堆栈"——因为根本没有正在运行的程序。不要忘记键入"run"。)如果它出错,不要忘记在运行gdb时添加第三个参数(core),否则将以相同的状态启动,而不是附加到任何特定的进程或内存映像。
    • 困难:如果您的程序确实在运行,但是您的gdb说"没有堆栈",那么您的堆栈指针可能被严重破坏。在这种情况下,您可能是某个地方的缓冲区溢出问题,严重到可以完全混合运行时状态。GCC 4.1支持使用-fstack-protector-all启用的Propolice"堆栈粉碎保护器"。它可以通过补丁添加到gcc 3.x中。

    您还需要在-g上使用调试标志进行构建。

    您也可以使用gdb打开核心转储文件(不过您需要-g)。


    当程序成功退出时,似乎发生了No stack问题。

    作为记录,我遇到了这个问题,因为我忘记了代码中的一个返回,这使得我的程序以失败代码退出。


    GCC没有提供这些信息的方法,您将不得不依赖于像gdb这样的外部程序。

    gdb可以在程序出现SEG故障后使用bt(backtrace的缩写)命令为您提供发生崩溃的线路。这将不仅提供崩溃的行,还提供程序的整个堆栈(这样您就可以看到在崩溃发生的地方调用了什么函数)。