段错误原因
1)、段错误究根到底就是访问了非法内存:
// 例子1:解引用空指针
int *p=NULL; printf("%d\n",*p); //因为内存低地址为代码段,不可访问?
// 例子2:访问含有非法值得内存
register int p =10; printf("%d\n",*p); //由于register关键字使变量存储到内核寄存器中,因此不能访问。
// 野指针:即定义指针时并未对其初始化,其指向的的位置式未知的。
// 对野指针解引用可能造成段错误或者导致程序崩溃。
// 防止方案:
/*
1;定义时初始化为NULL
2;解引用前赋值
3;使用完后指向NULL 每次使用指针之前记得赋值就好了
*/
2)、数组越界
// 堆中
p = malloc(256); p[-1] = 0; p[256] = 0; //访问了未知空间的内存
// 栈中
int *p=NULL;
int a[6];
p=a;
for(int i=0;i<10;i++)
{*p++=i;} //stack smashing detected 访问了未知空间的内存
3 )、scanf错误使用
int b; scanf("%d",b);//应为scanf("%d",&b);
4)、指针访问只读内存区
// 默认为const 指针
char *p=“abcddf”; *p=‘A’; //其实本质上错误原因和解引用空指针类似
5)、内存操作相关函数参数使用错误
memset(p1,p2,size); // p1或p2为 null或非法指针, size < 0 或 大于可操作区域
首先遇到这个问题,不要怀疑是系统原因,一定要仔细分析自已的代码,对于有内存或指针操作的函数,一定要仔细检查,一般来说都是以上原因,几乎没有意外了。
解决步骤
1)确认是否崩溃
查看系统日志, 如果程序真的崩溃了,会在系统中留下痕迹,
路径:/var/log/messages
一般的信息如下
程序名[2374]: segfault at7f0ed0bfbf70 ip00007f0edd646fe7 sp 00007f0ed3603978 error 4 inlibc-2.17.so[7f0edd514000+1b6000]
如果查不到,则表示是由别人发送指令或程序自行正常关闭的,可以不用管了。
2)找到崩溃具体库名称
libc-2.17.so[7f0edd514000+1b6000]可以看出错误发生在libc上,libc在此程序中映射的内存基址为7f0edd514000;
segfault at和error 4这两条信息可以得出是内存读出错,4的意义如下,可以对照参考:
bit2:值为1表示是用户态程序内存访问越界,值为0表示是内核态程序内存访问越界
bit1: 值为1表示是写操作导致内存访问越界,值为0表示是读操作导致内存访问越界
bit0: 值为1表示没有足够的权限访问非法地址的内容,值为0表示访问的非法地址根本没有对应的页面,也就是无效地址
2)计算库偏移地址
3、7f0ed0bfbf70,00007f0edd646fe7,00007f0ed3603978这三个值:第一个值为出错的地址,用处不大;第二个值为发生错误时指令的地址,这个值在有些错误时是错误的,下面会讲一下,第三个值为堆栈指针。
指令地址为:00007f0edd646fe7,libc指令的基地址为:7f0edd514000,可以根据这两个值相计算一下该指令的相对地址为132FE7,下面我们需要找到相对代码段地址为132FE7的地方为什么函数。
2)找到库文件所在目录,使用如下反汇编指令
objdump-tT libc-2.17.so | grep 132 (132为相对地址前几位,由于相对地址计算的位置可能不准确)
00000000000bf370l F .text 0000000000000132 __statfs_link_max
0000000000132080l F .text 0000000000000068 __nss_gshadow_lookup
0000000000132f50l F.text 0000000000000fd9 __strncmp_sse42
00000000001320f0l F.text 00000000000000a5 __strchr_sse42
0000000000132020l F .text 000000000000005e __nss_aliases_lookup
132f50和132fe7很接近,很大可能是这个函数出现,而且又是读地址非法,这个函数有可能会出错这个问题,__strncmp_sse42这个函数是被strncmp调用的,看到这个函数基本上可以确定应该是这个函数惹得祸,其它函数同理。
3)查找相关函数处理
一、在代码中重点对上述提示函数进行排查,不放过上述函数的任何一个参数,即使不是指针。
二、通过对以上函数的形参打log方法排查导常;
三、分析代码逻辑,重点排查内存使用函数;
通过以上排查后,问题基本上可以得到解决,祝大家好运~~~