在以C语言为代表的不少程序语言中,存在着一条默认的规则,那就是无法访问空指针。
那么空指针有什么特殊之处,为什么不能访问呢?
如果这样,那么这个地址应该是可以被CPU明确感知到它是特殊性的,不然的话,凭什么就不能被访问呢。
【老雷评语】黑木涯者,格蠹之少年也,在格蠹工作多年,调试技术不凡,每有疑难杂症,时有惊人之举,令老雷刮目相看。吾常嘱其将调试故事集结成文,他虽答应,但成文甚少。前日我再三嘱咐,终于在周五晚上收到此文,看了标题,差点惊掉老夫下巴。
传言即线索
“石牛对石鼓,银子万万五,谁人识的破,买断成都府”。
上面是一段流传很久的关于成都的传言,大多数人不会将这个事情当成真的。
但是,也有闲人真的按照张献忠走过的江河去挖掘,并且真的找到大量的黄金和首饰,找到了自然就要充公,现如今金沙博物馆中就陈列着当年张献忠所抢夺而来的金银珠宝。
由此看来,传言也不一定就是虚假。
【老雷评语】第一次读到上面这段,也是让我哭笑不得。
上面的传言只是一个乐子,接下来笔者再跟你讲一个,与本文有关的传言。
“不是只有0x0才叫空指针,访问0x0附近的内存也算是访问空指针”。
看到上面的传言后,你应该会更加坚定一个事实,那就是系统肯定可以明确的感知不可访问的内存区域,并且还知道这个内存区域对应的就是空指针。
理清进程无法访问内存的情况
先从内核角度介绍下用户态空间访问内存发生异常后的处理流程。Linux内核处理地址访问异常的逻辑已经非常完善了,所以从内核代码中,我们可以梳理出应用程序访问非法内存地址后的所有情况。
在用户态空间访问内存出现异常,有三种情况(想要分析有两种途径,一是通过dmesg信息辅助内核代码进行查找,二是使用挥码枪设置断点,看调用栈,对于当前的情况,不管是哪种途径都能分析到exc_page_fault等页异常处理函数)。
一是访问权限(读写可执行)不符合页的权限配置,这个时候access_error函数会检查出权限的异常,并抛出SIG_SEGV信号,终止程序。
exc_page_fault -> handle_page_fault -> do_user_addr_fault
-> if (access_error(error_code, vma)) -> bad_area_access_error
二是处理合法的页面故障(比如虚拟执行vdso、COW、缺页等场景),这个时候执行权会交到handle_mm_fault的手上。
exc_page_fault -> handle_page_fault -> do_user_addr_fault
-> if (access_error(error_code, vma)) { ... }
-> handle_mm_fault (...);
三是无法根据当前地址找到对应的VMA,这个时候内核会将该访问视为访问尚未分配的内存区域。
exc_page_fault -> handle_page_fault -> do_user_addr_fault
-> vma = lock_mm_and_fi

最低0.47元/天 解锁文章

923

被折叠的 条评论
为什么被折叠?



