Segmentation faults
主要的原因有
・内存访问违规行为
・无限or过深的递归处理
调查方法可以使用core dump
所谓core dump,是指在执行中的程序因错误而强制结束时,将当时程序使用的存储器空间的内容全部复制并保存在文件中的内容。用于调试工作。
例子
#include <stdio.h>
#include <string.h>
#define FNAME "/home/work/coredump/aaa/xxxxxxxxxxxxxxxxxxxxxxxx/data/zzzzzzzz/testfilexxxxx.txt"
#define FNAME_NEW "/home/work/coredump/aaa/xxxxxxxxxxxxxxxxxxxxxxxx/data/zzzzzzzz/testfilexxxxx_new.txt"
int main(void)
{
char cmd[128];
memset(cmd, 0, sizeof(cmd));
sprintf(cmd, "mv -f %s %s", FNAME_NEW, FNAME);
system(cmd);
return 0;
}
如果编译执行上面的代码,就会报Segmentation fault错误
# ./a.out
Segmentation fault
利用core dump调试
按照以下步骤进行调查
- 设置核心适配器的大小
- 用gcc的-g选项编译(调试信息授予)
- 生成运行→Core文件
- 在gdb中读取核心文件
- 调查原因之处
设置核心适配器的大小
首先运行此命令
[root@localhost coredump]# ulimit -c
0
[root@localhost coredump]# ulimit -c unlimited
[root@localhost coredump]# ulimit -c
unlimited
“ulimit”似乎是设置系统资源上限的命令。
“-c选项”设置核心转储的大小。
“unlimited”,也就是没有上限。
用gcc的-g选项编译,生成运行→Core文件
除了常规编译之外,还将“-g”添加到选项中
[root@localhost coredump]# gcc -g main.c
这允许您添加调试信息,如果编译成功,让我们运行
[root@localhost coredump]# ./a.out
Segmentation fault
Segmentation fault错误就出来了
如果你在这里显示文件列表
[root@localhost coredump]# ls -l
合計 168
-rwxr-xr-x. 1 root root 9656 4月 9 17:08 a.out
drwxr-xr-x. 3 root root 38 4月 9 17:04 aaa
-rw-------. 1 root root 245760 4月 9 17:08 core.3618
-rwxrwxrwx. 1 root root 404 4月 9 17:05 main.c
你有一个文件叫“core.XXXXX”。这是核心转储的文件
在gdb中读取核心文件
gbd是控制台处理的调试器,使用此gdb,可以通过打开核心转储文件来查看Segmentation fault发生时的调试信息。
[root@localhost coredump]# gdb a.out core.3618
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-110.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/work/coredump/a.out...done.
[New LWP 3618]
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x0000000000400602 in main () at main.c:15
15 }
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64
(gdb)
是说错误在“main.c的第15行”,看看细节
(gdb) bt
#0 0x0000000000400602 in main () at main.c:15
(gdb) frame 0
#0 0x0000000000400602 in main () at main.c:15
15 }
在“q→Enter”中,您可以退出gdb
调查原因之处
1 #include <stdio.h>
2 #include <string.h>
3
4 #define FNAME "/home/work/coredump/aaa/xxxxxxxxxxxxxxxxxxxxx xxx/data/zzzzzzzz/testfilexxxxx.txt"
5
6 #define FNAME_NEW "/home/work/coredump/aaa/xxxxxxxxxxxxxxxxxxxxx xxx/data/zzzzzzzz/testfilexxxxx_new.txt"
7
8 int main(void)
9 {
10 char cmd[128];
11 memset(cmd, 0, sizeof(cmd));
12 sprintf(cmd, "mv -f %s %s", FNAME_NEW, FNAME);
13 system(cmd);
14 return 0;
15 } // ←这行
原因应该是访问超过准备好的缓冲区,对于mv命令,共171Byte,完全越界了
mv -f /home/work/coredump/aaa/xxxxxxxxxxxxxxxxxxxxxxxx/data/zzzzzzzz/testfilexxxxx_new.txt /home/work/coredump/aaa/xxxxxxxxxxxxxxxxxxxxxxxx/data/zzzzzzzz/testfilexxxxx.txt
通过增加缓冲区大小可以解决此问题
char cmd[256];
结束语
在Linux的C语言中,发生了Segmentation fault,所以我试着使用核心转储解决了这个问题。
基本上原因是
・内存访问违规行为。
・无限or过深的递归处理。