我正在测试用于检测子进程何时进行segfaulted的代码.想象一下,当这段代码并不总是段错误时,我感到很惊讶:
#includeint 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
每次都正确.
我的错误是,我路过WNOHANG
到waitpid()
,在那里我应该已经传递零.我不知道我能想到什么!人们想知道问题是什么ksh
,但这是一个单独的问题.
写于NULL
将可靠段错误或总线错误.
有时,OS会将只读页面映射到零地址.因此,您有时可以阅读NULL
.
尽管C将NULL
地址定义为特殊地址,但该特殊状态的"实现"实际上由操作系统的虚拟内存(VM)子系统处理.
WINE和dosemu需要映射页面以NULL
获得Windows兼容性.请参阅mmap_min_addr
Linux内核以重建无法执行此操作的内核.
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.