段错误调试方法
程序源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *ptr = "hello"; //指针指向字符串常量区
*ptr = 'j'; //操作指针出现段错误
return 0;
}
解决方法1:gdb命令(推荐)
$gcc -g test.c -o test//产生调试工具,可以调用gdb;并且将可执行文件改为test,默认为a.out
$gdb test //进入gdb调试模式
Reading symbols from a.out...
(gdb)
r //gdb模式下r表示运行
/**************出现错误信息*****************/
Program received signal SIGSEGV, Segmentation fault.
0x0000555555555147 in main (argc=1, argv=0x7fffffffde08) at 1.c:13
13 *ptr = 'j';
gdb模式下常用命令
//-q参数可以屏蔽一些gdb版本等相关信息;
$gdb -q a.out
//输入list(l)即可查看程序源码
(gdb)l
//输入run(r)开始运行程序,直到遇到“断点”或者“结束”:
(gdb)r
//输入 break(b)+数字 可以对程序进行断点操作(数字就是设置断点的代码行数)
(gdb)b 5
//输入 info breakpoints 即可查看断点信息:
Num: 断点编号
Disp:断点执行一次之后是否有效(keep:有效 dis:无效)
Enb: 当前断点是否有效 (y:有效 n:无效)
Address:内存地址
What:位置
next(n)://单步执行程序,但是遇到函数时会直接跳过函数,不进入函数
step(s)://单步执行程序,但遇到函数会进入函数
continue(c)://继续执行程序,直到遇到断点或结束
详细介绍可参考http://t.csdn.cn/fKz55
解决方法2:addr2line
$gcc -g 3.c
$./a.out
$dmesg
//通过dmesg 得到段错误相对地址 0000560cd9ed3147-560cd9ed3000+1000 == 1147
a.out[3426]: segfault at 560cd9ed4004 ip /*0000560cd9ed3147*/ sp 00007ffeb76cc920 error 6 in a.out/*[560cd9ed3000+1000]*/
//任意segfault都可以计算出相对地址
$addr2line 1147 a.out
/home/hqyj/IO/day1/3.c:13
??:0
/*****错误信息为3.c中13行*******/
解决方法3:printf
在地址操作的地方打印行号
printf("%s %d",__func__,__LINE__); //打印本行所在函数和行号
...
printf("%s %d",__func__,__LINE__);
//若第一个打印信息成功第二个打印信息失败,则错误出现在两个打印之间