我正在测试设计用于检测子进程何时出现分段错误的代码。想象一下,当这段代码并不总是分段错误时,我感到惊讶:
#include <stdio.h>
int main() {
char *p = (char *)(unsigned long)0;
putchar(*p);
return 0;
}
我是在DebianLinux2.6.26内核下运行的;我的外壳是来自Debian ksh
包的AT&T ksh
,版本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
在纯ksh
下运行表明,分段错误也很少见:
Running...
Running...
Running...
Running...
Running...
Running... Memory fault
Running...
有趣的是,bash
每次都能正确地检测到分段故障。
我有两个问题:
kill(getpid(), SIGSEGV)
,但是我得到了类似的结果。编辑:jbcreix的答案是:我的分段故障检测器坏了。我被愚弄是因为ksh
也有同样的问题。我和bash
试过了,bash
每次都做得对。
我的错误是我把WNOHANG
传递给了waitpid()
,在那里我应该传递零。我不知道我会怎么想!人们想知道ksh
是怎么回事,但这是另外一个问题。
发布于 2009-11-14 19:43:08
写入NULL
将可靠地分割故障或总线错误。
有时,操作系统会将只读页映射到零地址。因此,您有时可以从NULL
中读取。
尽管C将NULL
地址定义为特殊地址,但该特殊状态的“实现”实际上是由操作系统的虚拟内存(VM)子系统处理的。
为了实现Windows兼容性,葡萄酒和多斯莫需要在NULL
上映射页面。请参阅Linux内核中的mmap_min_addr
,以重新构建不能这样做的内核。
mmap_min_addr
目前是一个热门话题,这是因为OpenBSD的一个相关的开发和对Linus (显然是Linux名声)的公开攻击。
如果您愿意以这种方式对子程序进行编码,则始终可以调用: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.
发布于 2009-11-14 19:41:26
我不知道为什么它没有一致的行为。我想这不像读书那样挑剔。或者诸如此类的事情,尽管我可能完全错了。
试着用空写。这对我来说似乎是一致的。我不知道你为什么要用这个。:)
int main()
{
*(int *)0 = 0xFFFFFFFF;
return -1;
}
发布于 2009-11-14 19:49:32
维基百科的第二个问题的答案是:
int main(void)
{
char *s = "hello world";
*s = 'H';
}
https://stackoverflow.com/questions/1735349
复制相似问题