概述
分段错误原因在于程序读写了非法位置的内存。
而程序内存分为不同的段,segments
程序指令放在 text segment
数据(编译时定义的变量、数组)放在 data segment
函数中定义的临时变量放在 stack segment
函数运行时分配的 内存 如malloc,放在 heap segment
当对某变量引用时,地址却在此变量所在的段外时,或者 企图对一个只读段进行写操作时,segfault就会产生。
实践中,segfaults的出现,总是因为 读写了一个不存在的数组元素,或者没有合适的定义一个指针就使用了它,或者偶然地把一个变量的值作为了地址。
段错误举例
数组越界相关的例子
Case A |
---|
/* "Array out of bounds" error valid indices for array foo are 0, 1, ... 999 */ int foo[1000]; for (int i = 0; i <= 1000 ; i++) foo[i] = i; |
Case B |
/* Illegal memory access if value of n is not in the range 0, 1, ... 999 */ int n; int foo[1000]; for (int i = 0; i < n ; i++) foo[i] = i; |
Case C |
/* Illegal memory access because no memory is allocated for foo2 */ float *foo, *foo2; foo = (float*)malloc(1000); foo2[0] = 1.0; |
错误使用指针的例子:
int foo = 0; scanf("%d", foo); /* Note missing & sign ; correct usage would have been &foo */
另外,写只读内存,以及栈空间溢出,都会导致Segfaults
栈空间溢出也可能不是程序bug,而是你的shelll设置的栈太小了。
找出越界数组
找出越界数组引用
一些编译器中含有越界检查选项,可以在数组引用重插入代码,在调试的时候检测是否越界。
检查shell的限制
使用ulimit -s查看linux默认栈空间大小 ,也可以用ulimit -s xxx设置大小。
使用调试器诊断段错误
当程序出现segfaults时候,会把崩溃时候的内存中的一部分内容dump到core文件中,用gdb core启动调试器,
然后用 backtrace命令查看什么地方出现了crash.
如果backtrace不行,则需要启动调试器,跟踪,此时代码需要再无优化的情况下编译,加上-g 则会把代码行信息嵌入
程序中。