linux segmentation fault原因
2015-10-12 21:25
351 查看
最近进行LINUX环境吓开发时总是遇到Segmentation fault这个问题,很是头疼。
原文参见http://www.cnblogs.com/no7dw/archive/2013/02/20/2918372.html
1.什么是“Segmentation fault in Linux”?(参见http://www.cnblogs.com/no7dw/archive/2013/02/20/2918372.html)
它是“计算机软件操作过程中的一种错误情况”。文字描述了SIGSEGV在何时发生,即“当程序试图访问不被允许访问的内存区域(比如,尝试写一块属于操作系统的内存),或以错误的类型访问内存区域(比如,尝试写一块只读内存)。这个描述是准确的。为了加深理解,我们再更加详细的概括一下SIGSEGV。
Ø SIGSEGV是在访问内存时发生的错误,它属于内存管理的范畴
Ø SIGSEGV是一个用户态的概念,是操作系统在用户态程序错误访问内存时所做出的处理。
Ø 当用户态程序访问(访问表示读、写或执行)不允许访问的内存时,产生SIGSEGV。
Ø 当用户态程序以错误的方式访问允许访问的内存时,产生SIGSEGV。
从用户态程序开发的角度,我们并不需要理解操作系统复杂的内存管理机制,这是和硬件平台相关的。但是,了解内核发送SIGSEGV信号的流程,对我们理解SIGSEGV是很有帮助的。在《Understanding Linux Kernel Edition 3》和《Understanding the Linux Virtual Memory Manager》相关章节都有一幅总图对此描述,对比之下,笔者认为ULK的图更为直观。
图1红色部分展示了内核发送SIGSEGV信号给用户态程序的总体流程。当用户态程序访问一个会引发SIGSEGV的地址时,硬件首先产生一个page
fault,即“缺页异常”。在内核的page
fault处理函数中,首先判断该地址是否属于用户态程序的地址空间[*]。以Intel的32bit
IA32架构的CPU为例,用户态程序的地址空间为[0,3G],内核地址空间为[3G,4G]。如果该地址属于用户态地址空间,检查访问的类型是否和该内存区域的类型是否匹配,不匹配,则发送SIGSEGV信号;如果该地址不属于用户态地址空间,检查访问该地址的操作是否发生在用户态,如果是,发送SIGSEGV信号。
简单而言,就是访问了没有权限的地址。
2.指针越界和SIGSEGV
经常看到有帖子把两者混淆,而这两者的关系也确实微妙。在此,我们把指针运算(加减)引起的越界、野指针、空指针都归为指针越界。SIGSEGV在很多时候是由于指针越界引起的,但并不是所有的指针越界都会引发SIGSEGV。一个越界的指针,如果不解引用它,是不会引起SIGSEGV的。而即使解引用了一个越界的指针,也不一定会引起SIGSEGV。这听上去让人发疯,而实际情况确实如此。SIGSEGV涉及到操作系统、C库、编译器、链接器各方面的内容,我们以一些具体的例子来说明。
2.1错误的访问类型引起的SIGSEGV
2.2访问了不属于进程地址空间的内存
2.3访问了不存在的内存
2.4栈溢出了,有时SIGSEGV,有时却啥都没发生
2.5 函数跳转到了一个非法的地址上执行
3.如何避免SIGSEGV
尽量按照C标准写程序。之所以说是尽量,是因为C标准有太多平台相关和无定义的行为,而其中一些实际上已经有既成事实的标准了。例如C标准中,一个越界的指针导致的是无定义的行为,而在实际情况中,一个越界而未解引用的指针是不会带来灾难后果的。
原文参见http://www.cnblogs.com/no7dw/archive/2013/02/20/2918372.html
1.什么是“Segmentation fault in Linux”?(参见http://www.cnblogs.com/no7dw/archive/2013/02/20/2918372.html)
它是“计算机软件操作过程中的一种错误情况”。文字描述了SIGSEGV在何时发生,即“当程序试图访问不被允许访问的内存区域(比如,尝试写一块属于操作系统的内存),或以错误的类型访问内存区域(比如,尝试写一块只读内存)。这个描述是准确的。为了加深理解,我们再更加详细的概括一下SIGSEGV。
Ø SIGSEGV是在访问内存时发生的错误,它属于内存管理的范畴
Ø SIGSEGV是一个用户态的概念,是操作系统在用户态程序错误访问内存时所做出的处理。
Ø 当用户态程序访问(访问表示读、写或执行)不允许访问的内存时,产生SIGSEGV。
Ø 当用户态程序以错误的方式访问允许访问的内存时,产生SIGSEGV。
从用户态程序开发的角度,我们并不需要理解操作系统复杂的内存管理机制,这是和硬件平台相关的。但是,了解内核发送SIGSEGV信号的流程,对我们理解SIGSEGV是很有帮助的。在《Understanding Linux Kernel Edition 3》和《Understanding the Linux Virtual Memory Manager》相关章节都有一幅总图对此描述,对比之下,笔者认为ULK的图更为直观。
图1红色部分展示了内核发送SIGSEGV信号给用户态程序的总体流程。当用户态程序访问一个会引发SIGSEGV的地址时,硬件首先产生一个page
fault,即“缺页异常”。在内核的page
fault处理函数中,首先判断该地址是否属于用户态程序的地址空间[*]。以Intel的32bit
IA32架构的CPU为例,用户态程序的地址空间为[0,3G],内核地址空间为[3G,4G]。如果该地址属于用户态地址空间,检查访问的类型是否和该内存区域的类型是否匹配,不匹配,则发送SIGSEGV信号;如果该地址不属于用户态地址空间,检查访问该地址的操作是否发生在用户态,如果是,发送SIGSEGV信号。
简单而言,就是访问了没有权限的地址。
2.指针越界和SIGSEGV
经常看到有帖子把两者混淆,而这两者的关系也确实微妙。在此,我们把指针运算(加减)引起的越界、野指针、空指针都归为指针越界。SIGSEGV在很多时候是由于指针越界引起的,但并不是所有的指针越界都会引发SIGSEGV。一个越界的指针,如果不解引用它,是不会引起SIGSEGV的。而即使解引用了一个越界的指针,也不一定会引起SIGSEGV。这听上去让人发疯,而实际情况确实如此。SIGSEGV涉及到操作系统、C库、编译器、链接器各方面的内容,我们以一些具体的例子来说明。
2.1错误的访问类型引起的SIGSEGV
2.2访问了不属于进程地址空间的内存
2.3访问了不存在的内存
2.4栈溢出了,有时SIGSEGV,有时却啥都没发生
2.5 函数跳转到了一个非法的地址上执行
3.如何避免SIGSEGV
尽量按照C标准写程序。之所以说是尽量,是因为C标准有太多平台相关和无定义的行为,而其中一些实际上已经有既成事实的标准了。例如C标准中,一个越界的指针导致的是无定义的行为,而在实际情况中,一个越界而未解引用的指针是不会带来灾难后果的。
相关文章推荐
- 《王保明老师----Linux开发学习笔记》------讲03:进程 -----fork( )函数 的疑问
- 《王保明老师----Linux开发学习笔记》------讲03:进程
- 关于linux小知识
- Ubuntu下安装为知笔记Linux版本
- Ubuntu安装搜狗输入法Linux版
- linux inittab文件 6种启动模式
- linux下搭建J2EE开发环境以及IDE的安装
- Linux内核工程导论——内核为何使用C语言
- ld returned 1 exit status这类问题如何处理
- linux 同步IO: sync、fsync与fdatasync
- linux su命令参数及用法详解(linux切换用户命令)
- Linux下rename批量改变同文件夹的文件后缀名
- Linux进程间通信——使用共享内存
- linux 16个应该了解的命令
- linux基础命令
- 第 二 十 八 天 :高 可 用 负 载 均 衡 集 群 搭 建
- linux 需改环境变量
- linux命令dd
- 【转】Ubuntu分区详细介绍
- Linux下从源码编译安装软件中3个命令之间的关系