定位Segmentation Fault最简单的方法

11

我是一名新手程序员,今天遇到了第一个段错误(Segmentation Fault)。在阅读了关于什么是段错误的所有有用信息后(感谢此网站和维基百科提供的详细解释),我正在尝试确定找到故障发生位置的最简单方法。代码是用C语言编写的,错误发生在基于*NIX系统上(我不确定是哪个...但99%确定是Linux)。由于我正在编译多个相当冗长的文件,因此无法粘贴我的代码。我只是希望得到你们所观察到的最佳实践。谢谢你们的帮助。

附:我认为错误可能来自于解除引用空指针或使用未初始化的指针,但我可能错了。


7
第一次段错误?我可以保证这不会是最后一次。;-) - netcoder
4个回答

19

使用调试器,例如gdb或者如果不适用的话可以使用strace工具来更好地了解段错误发生的位置。

如果你使用gcc,确保使用-g选项进行编译,以包含调试信息。然后,gdb会显示出源代码中精确的出错位置。

举个例子,假设我们有这样一个明显出错的程序:

new.c

#include <stdio.h>

int main()
{
        int *i = 0x478734;
        printf("%d", *i);
}

我们使用 gcc -g new.c -o new 进行编译,然后使用 gdb new 启动 gdb 会话:

在交互式会话中输入 run 命令,其他的就很清楚了:

(gdb) run
Starting program: /home/Tibor/so/new
[New Thread 9596.0x16a0]
[New Thread 9596.0x1de4]

Program received signal SIGSEGV, Segmentation fault.
0x0040118a in main () at new.c:6
6               printf("%d", *i);
(gdb)

正如DasMoeh和netcoder所指出的那样,当发生段错误时,您可以在交互式会话中使用backtrace命令来打印调用堆栈。这可以帮助进一步确定段错误的位置。

非常感谢。这会帮助这个过程不那么令人厌烦 :) 我会尽快接受你的答案 :) - TZPike05
遗憾的是您没有提到“回溯”,但还是加1。 - netcoder

5

最简单的方法是使用valgrind。它将确定无效访问发生的位置(以及其他没有导致崩溃但仍然无效的问题)。当然,实际问题可能在代码的其它位置(例如:无效指针),所以下一步是检查源代码,如果还是困惑,就使用调试器。


+1 Valgrind非常有用,但如果没有调试标志,作用不大。 - netcoder

2

1

我重新打开这篇帖子,因为我刚刚使用gcc纠正了一个segfault。

你应该考虑使用标志-fsanitize=address,有时可以高精度地显示您的segfault。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接