要谈segment fault,必需要谈指针。程序员
指针的本质是什么?只不过是一种带*的数据类型,其特点有:指针
一、宽度ip
二、声明内存
三、赋值变量
四、++与--cli
五、+与-file
六、求差值数据类型
七、比较程序
当声明int *ptr = 0x0以后,ptr1就是一个指针变量了,im
能够对ptr1作++,--,+,-等各类操做,
然而不能访问ptr地址中的内容,由于访问的是非法内存地址0x0(内核空间地址?)。
当声明int *prt2 = 0x12345678以后,prt2就是一个指针变量了,
能够对ptr1作++,--,+,-等各类操做,
也能够访问ptr地址中的内容,由于访问的是合法内存地址0x12345678(用户空间地址)。
从Linux内核角度来看,segment fault发生有三种缘由:
当应用程序访问一个虚拟地址时,正常状况下,你其实是在访问处于某个VMA中的一个地址而已。若是你正常的访问,那么一切都如你所愿,MMU读入内核task_struct中记录的表格,而后,虚拟地址正确地转换到物理内存地址。可是,若是: 1. 若是内核标明这个VMA是只读的,但你恰恰往这个地址段中写,内核天然不能容忍应用程序犯这样的错误。2. 你可能去访问虚拟地址空间中某个根本没有映射的hole. 刚学指针的 C 程序员老是觉得本身无所不能,好比:int *p = (int *)0x543;*p = 5;而后运行程序时,他确定会很开心地收到段错误,而后为此郁闷一个下午。究其缘由其实很简单: 0x543这个地址没有处于一个合法的VMA中,它可能处于一个根本没有和物理内存映射的虚拟空间的hole中. 对于教训新手 C 程序员来讲,内核仍是很是乐意的,由于新手C程序员离可以驾驭Linux内核的水准至少还差那么三五年时间。3. 应用程序访问内核空间(0xc000 0000 --> 0xffff ffff),内核早早就说明那不是应用程序应该访问的地址范围。竟然敢打内核的主意!这个应用程序必定活得很是不耐烦,是在找抽。