mylinuxer

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

要谈segment fault,必须要谈指针。

指针的本质是什么?只不过是一种带*的数据类型,其特色有:

1、宽度

2、声明

3、赋值

4、++与--

5、+与-

6、求差值

7、比较

 

当声明int *ptr = 0x0之后,ptr1就是一个指针变量了,

可以对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),内核早早就说明那不是应用程序应该访问的地址范围。居然敢打内核的主意!这个应用程序一定活得非常不耐烦,是在找抽。

posted on 2015-12-31 15:38  mylinuxer  阅读(986)  评论(0编辑  收藏  举报