如何确定导致分段错误的代码中的错误在哪里?

我的编译器(gcc)可以显示程序中错误的位置吗?


当前回答

Lucas关于核心转储的回答很好。在我的.cshrc中,我有:

alias core 'ls -lt core; echo where | gdb -core=core -silent; echo "\n"'

输入“core”显示反向跟踪。和日期戳,以确保我在看正确的文件:(。

补充:如果存在堆栈损坏错误,那么应用于核心转储的回溯通常是垃圾。在这种情况下,根据接受的答案(假设错误很容易重现),在gdb中运行程序可以得到更好的结果。同时也要注意多个进程同时转储核心;有些操作系统会将PID添加到核心文件的名称中。

其他回答

Lucas关于核心转储的回答很好。在我的.cshrc中,我有:

alias core 'ls -lt core; echo where | gdb -core=core -silent; echo "\n"'

输入“core”显示反向跟踪。和日期戳,以确保我在看正确的文件:(。

补充:如果存在堆栈损坏错误,那么应用于核心转储的回溯通常是垃圾。在这种情况下,根据接受的答案(假设错误很容易重现),在gdb中运行程序可以得到更好的结果。同时也要注意多个进程同时转储核心;有些操作系统会将PID添加到核心文件的名称中。

以上答案都是正确的,建议回答;如果前面提到的方法都不能使用,这个答案只是作为最后的手段。

If all else fails, you can always recompile your program with various temporary debug-print statements (e.g. fprintf(stderr, "CHECKPOINT REACHED @ %s:%i\n", __FILE__, __LINE__);) sprinkled throughout what you believe to be the relevant parts of your code. Then run the program, and observe what the was last debug-print printed just before the crash occurred -- you know your program got that far, so the crash must have happened after that point. Add or remove debug-prints, recompile, and run the test again, until you have narrowed it down to a single line of code. At that point you can fix the bug and remove all of the temporary debug-prints.

这很乏味,但它的优点是几乎可以在任何地方工作——如果由于某种原因无法访问stdout或stderr,或者如果您试图修复的bug是一个竞态条件,其行为会随着程序的时间变化而变化(因为调试打印会减慢程序并改变其时间),则可能无法工作。

您还可以使用一个核心转储,然后用gdb检查它。要获得有用的信息,还需要使用-g标志进行编译。

每当你收到这样的信息:

 Segmentation fault (core dumped)

一个核心文件被写入当前目录。您可以使用命令检查它

 gdb your_program core_file

该文件包含程序崩溃时内存的状态。核心转储在软件部署期间非常有用。

确保您的系统没有将核心转储文件大小设置为零。你可以通过以下方法将其设置为无限:

无限制

不过小心!核心转储可能变得巨大。

如果你们中有人(像我一样!)也在寻找同样的问题,但是使用gfortran而不是gcc,那么现在编译器要强大得多,在使用调试器之前,您还可以尝试这些编译选项。对我来说,这准确地确定了发生错误的代码行,以及我访问的哪个变量越界导致了分割错误错误。

-O0 -g -Wall -fcheck=all -fbacktrace

此外,你可以给valgrind一个尝试:如果你安装valgrind并运行

valgrind --leak-check=full <program>

然后它将运行您的程序并显示任何段错误的堆栈跟踪,以及任何无效的内存读写和内存泄漏。它真的很有用。