段错误(Segmentation Fault),是指程序试图访问一段不可访问的内存区域时发生的错误。
实例
英文介绍
A segmentation fault (often shortened to segfault) is a particular error condition that can occur during the operation of computer software. In short, a segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (e.g., attempts to write to a read-only location, or to overwrite part of the operating system). Systems based on processors like the Motorola 68000 tend to refer to these events as Address or Bus errors.
On
Unix-like operating systems, a process that accesses invalid memory receives the SIGSEGV signal. On
Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception.
另外,这里有个基本上对照的中文解释,来自库
扩展阅读1;
Quote
一旦一个程序发生了越界访问,
cpu就会产生相应的保护,于是segmentation fault就出现
了通过上面的解释,段错误应该就是访问了不可访问的内存,这个内存区要么是不存在的,
要么是受到系统保护的,还有可能是缺少文件或者文件损坏。
段错误形式
在编程中以下几类做法容易导致段错误,基本上是错误地使用指针引起的。
(1)访问系统
数据区,尤其是往系统保护的
内存地址写数据最常见就是给一个指针以0地址。
(2)内存越界(数组越界,变量类型不一致等): 访问到不属于你的内存区域。
下面将就以下的一个存在段错误的程序介绍几种调试方法:
出错并退出。作为一个熟练的
C/C++程序员,以上代码的
bug应该是很清楚的,因为它尝试操作地址为0的内存区域,而这个内存区域通常是不可访问的禁区,当然就会出错了。我们尝试
编译运行它:
查找段错误
这种方法也是被大众所熟知并广泛采用的方法,首先我们需要一个带有调试信息的
可执行程序,所以我们加上“-g -rdynamic”的参数进行编译,然后用
gdb调试运行这个新编译的程序,具体步骤如下:
不用一步步调试我们就找到了出错位置d.c文件的第4行,其实就是如此的简单。
从这里我们还发现进程是由于收到了
SIGSEGV信号而结束的。通过进一步的查阅文档(man 7 signal),我们知道SIGSEGV默认handler的动作是打印“段错误”的出错信息,并产生Core文件,由此我们又产生了方法二。
分析文件
以 上资料摘自
man page(man 5
core)。不过奇怪了,我的系统上并没有找到core文件。后来,忆起为了渐少系统上的
垃圾文件的数量,禁止了core文件的生成,查看了以下果真如此,将系统的core文件的大小限制在512K大小,再试:
分析工具
利用backtrace和objdump进行分析
xiaosuo@gentux test $ ./a.out
Obtained 5 stack frames.
./a.out(dump+0x19) [0x80486c2]
[0xffffe420]
./a.out(main+0x35) [0x804876f]
典型段错误
1,
被装载时,系统把“hello world” 连同其它的
字符串和const型数据放入到内存的只读区。执行时,一个变量s被设为指向该字符串的位置,当再试图向该位置写时,就会产生段错误。
2,
因为该代码只创建了一个空指针,并没有指向一个具体空间,当赋值时,产生段错误。
3,