我是一名新手程序员,今天遇到了第一个段错误(Segmentation Fault)。在阅读了关于什么是段错误的所有有用信息后(感谢此网站和维基百科提供的详细解释),我正在尝试确定找到故障发生位置的最简单方法。代码是用C语言编写的,错误发生在基于*NIX系统上(我不确定是哪个...但99%确定是Linux)。由于我正在编译多个相当冗长的文件,因此无法粘贴我的代码。我只是希望得到你们所观察到的最佳实践。谢谢你们的帮助。
附:我认为错误可能来自于解除引用空指针或使用未初始化的指针,但我可能错了。
我是一名新手程序员,今天遇到了第一个段错误(Segmentation Fault)。在阅读了关于什么是段错误的所有有用信息后(感谢此网站和维基百科提供的详细解释),我正在尝试确定找到故障发生位置的最简单方法。代码是用C语言编写的,错误发生在基于*NIX系统上(我不确定是哪个...但99%确定是Linux)。由于我正在编译多个相当冗长的文件,因此无法粘贴我的代码。我只是希望得到你们所观察到的最佳实践。谢谢你们的帮助。
附:我认为错误可能来自于解除引用空指针或使用未初始化的指针,但我可能错了。
使用调试器,例如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)
backtrace
命令来打印调用堆栈。这可以帮助进一步确定段错误的位置。最简单的方法是使用valgrind
。它将确定无效访问发生的位置(以及其他没有导致崩溃但仍然无效的问题)。当然,实际问题可能在代码的其它位置(例如:无效指针),所以下一步是检查源代码,如果还是困惑,就使用调试器。
Tibors的回答很棒,点个赞。
对于较大的程序或使用额外库时,使用gdb查看回溯信息也可能非常有用:ftp://ftp.gnu.org/pub/old-gnu/Manuals/gdb/html_node/gdb_42.html
我重新打开这篇帖子,因为我刚刚使用gcc纠正了一个segfault。
你应该考虑使用标志-fsanitize=address,有时可以高精度地显示您的segfault。