-
产生段错误的原因
段错误就是指某一进程访问了不属于它权限范围的内存空间,比如:访问了不存在的内存,访问了受系统保护的内存,访问了只读的内存等。下面是一段会产生段错误的实例代码:main.c
#include <stdio.h> #include <string.h> void test() { char *p = NULL; *p = 'T'; } int main() { test(); return 0; }
编译运行main.c,会输出段错误提示
wbhuang@ubuntu:~/src/test_debug_segmentation$ gcc -g -o main main.c wbhuang@ubuntu:~/src/test_debug_segmentation$ ./main Segmentation fault (core dumped) |
-
段错误调试方法
方法一:使用gdb进行调试
编译时确保gcc的带参数"-g",启动gdb,调试main
wbhuang@ubuntu:~/src/test_debug_segmentation$ gdb main GNU gdb (GDB) 7.5-ubuntu Copyright (C) 2012 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 "i686-linux-gnu" . For bug reporting instructions, please see: <http: //www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/wbhuang/src/test_debug_segmentation/main...done. (gdb) |
执行gdb命令r/run,则会输出段错误的相关信息
(gdb) r Starting program: /home/wbhuang/src/test_debug_segmentation/main Program received signal SIGSEGV, Segmentation fault. 0x080483ec in test () at main.c:7 7 *p = 'T' ; (gdb) |
方法二:使用objdump
首先先执行./main输出提示段错误,然后执行dmesg命令,在输出信息的最底下找到最近一次发生段错误的记录
[ 4522.506831] main[3154]: segfault at 0 ip 080483ec sp bf80c2c0 error 6 in main[8048000+1000] |
这里有两个重要信息,一个是"segfault at 0"和"ip 080483ec",这就是说发生断错误的地址为:0,而指令指针地址为:080483ec。
接下来使用objdump命令,objdump是用来查看目标文件(二进制文件)或者可执行的目标文件的构成的工具
wbhuang@ubuntu:~/src/test_debug_segmentation$ objdump -d ./main > maindump |
用vim查看maindump文件,下面的141 80483ec:这一行就是段错误发生时执行的指令了,接下来只需将汇编代码匹配到源码就Ok了。
./main: file format elf32-i386 3 4 5 Disassembly of section .init: 6 7 08048294 <_init>: 8 8048294: 53 push %ebx 9 8048295: 83 ec 08 sub $0x8,%esp ... ... 135 080483dc <test>: 136 80483dc: 55 push %ebp 137 80483dd: 89 e5 mov %esp,%ebp 138 80483df: 83 ec 10 sub $0x10,%esp 139 80483e2: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp) 140 80483e9: 8b 45 fc mov -0x4(%ebp),%eax 141 80483ec: c6 00 54 movb $0x54,(%eax) 142 80483ef: c9 leave 143 80483f0: c3 ret ... ... |