段错误(segment 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.
Segmentation is one approach to memory management and protection in the operating system. It has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.
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.程序试图访问一个不允许访问的内存位置
2.程序试图对内存位置做不合法的操作(比如去写一个只读的位置,例如一个程序加载到内存中后,它的代码段肯定是只读的)
3.程序试图改写操作系统所用的内存空间
为什么叫做段错误?这是由于在X86机器上,操作系统管理内存的访问时需要用到段式管理(好像linux通过某种方法把它转变为页式管理),一个程序运行起来后,一般会有CS,DS,SS,ES(代码段,数据段,堆栈段,附加数据段),C ,C++语言允许我们直接对内存地址(逻辑地址)进行操作,这个内存地址经过操作系统对应的内存管理方式,映射到实际的物理内存地址上。通常在代码中我们能操作的地址是DS,SS段里面的,如果给出的地址非法(操作系统判定)那么这个映射就无法完成,程序就没法跑下去,报段错误(内存段式映射错误)。
举几个段错误的例子:
1.访问不允许访问的内存
NULL其实就是地址0,我觉得不像是平时别人解释的没为p分配空间就引起了段错误,可能这个0地址映射到的就是操作系统的内存空间吧。
2.以不正确的访问方式存取内存地址
首先,"abc"是存在于只读数据段,p指向它,然后对这个地址进行写操作,明显是不允许的。
3.malloc出来的地址和free的地址不一致 这个不是发生段错误,是未定义的异常。
1 char *p = NULL;
2
3 p = (char *)malloc(2);
4 if ( p == NULL )
5 {
6 perror("mallc");
7 return -1;
8 }
9
10 p++;
11
12 if ( p != NULL )
13 {
14 free(p);
15 p = NULL;
16 }
这个是最近我工作中遇到的问题,由于不小心修改了指针的指向,导致free时居然出现段错误。原因,man 3 free的结果:
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
free的这个指针必须是由调用它之前的那个malloc calloc realloc 返回的指针,如果不是,将会发生不可预知的行为,我见到的是core dump。还有个小细节,free时为什么要判断p是否为NULL?之前我一直自以为是的认为是free(NULL)会报段错误,结果试了一下发现free空指针完全没问题,其实写成这种固定模式主要是为了防止使用野指针,一段free后的内存仍然时可以读写的,但是会引发莫名其妙的问题,因为它们out of control了,还有一个就是防止double free。