当前位置:  开发笔记 > 编程语言 > 正文

为什么Linux程序derefrences(char*)0并不总是段错误?

如何解决《为什么Linux程序derefrences(char*)0并不总是段错误?》经验,为你挑选了1个好方法。

我正在测试用于检测子进程何时进行segfaulted的代码.想象一下,当这段代码并不总是段错误时,我感到很惊讶:

#include 

int main() {
  char *p = (char *)(unsigned long)0;
  putchar(*p);
  return 0;
}

我在Debian Linux 2.6.26内核下运行; 我的shell是ksh93来自Debian ksh软件包的AT&T ,版本M 93s + 2008-01-31.有时这个程序会出现段错误,但除此之外它只是以非零退出状态静默终止但没有消息.我的信号检测程序报告如下:

segfault terminated by signal 11: Segmentation fault
segfault terminated by signal 53: Real-time signal 19
segfault terminated by signal 11: Segmentation fault
segfault terminated by signal 53: Real-time signal 19
segfault terminated by signal 53: Real-time signal 19
segfault terminated by signal 53: Real-time signal 19
segfault terminated by signal 53: Real-time signal 19

在pure下运行ksh表明segfault也很少见:

Running... 
Running... 
Running... 
Running... 
Running... 
Running... Memory fault
Running... 

有趣的是,bash每次都能正确检测到段错误.

我有两个问题:

    谁能解释这种行为?

    任何人都可以建议一个简单的C程序,它会在每次执行时可靠地进行段错误吗 我也尝试过kill(getpid(), SIGSEGV),但是得到了类似的结果.


编辑:jbcreix有答案:我的segfault探测器坏了.我被骗了,因为ksh有同样的问题.我试过bash并且bash每次都正确.

我的错误是,我路过WNOHANGwaitpid(),在那里我应该已经传递零.我不知道我能想到什么!人们想知道问题是什么ksh,但这是一个单独的问题.



1> Heath Hunnic..:

NULL将可靠段错误或总线错误.

有时,OS会将只读页面映射到零地址.因此,您有时可以阅读NULL.

尽管C将NULL地址定义为特殊地址,但该特殊状态的"实现"实际上由操作系统的虚拟内存(VM)子系统处理.

WINE和dosemu需要映射页面以NULL获得Windows兼容性.请参阅mmap_min_addrLinux内核以重建无法执行此操作的内核.

mmap_min_addr 目前是一个热门话题,因为相关的漏洞利用以及来自Theo de Raadt的Linus(显然是Linux成名)的公开火焰,OpenBSD的努力.

如果您愿意以这种方式对孩子进行编码,您可以随时致电: raise(SIGSEGV);

此外,您可以从以下位置获取保证到段错误的指针: int *ptr_segv = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS, -1, 0);

PROT_NONE保留无法访问的内存的关键在哪里.对于32位Intel Linux,PAGE_SIZE为4096.

推荐阅读
农大军乐团_697
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有