为什么Linux的程序,derefrences(字符*)0并不总是出现段错误? [英] Why does Linux program that derefrences (char*)0 not always segfault?

查看:270
本文介绍了为什么Linux的程序,derefrences(字符*)0并不总是出现段错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我测试code,它被设计为当一个子进程segfaulted检测。想象一下,当这code总是不段错误我感到惊讶:

I'm testing code that is designed to detect when a child process has segfaulted. Imagine my surprised when this code does not always segfault:

#include <stdio.h>

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

我下一个Debian的Linux 2.6.26内核上运行;我的shell是AT&amp; T公司 ksh93的从Debian KSH 包,版本中号93s + 2008-01-31。有时,这种程序段错误,但否则它只是一个非零退出状态,但没有消息默默终止。我的信号检测方案报告如下:

I'm running under a Debian Linux 2.6.26 kernel; my shell is the AT&T ksh93 from the Debian ksh package, Version M 93s+ 2008-01-31. Sometimes this program segfault but otherwise it simply terminates silently with a nonzero exit status but no message. My signal-detecting program reports the following:

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 under pure ksh shows that the segfault is also rare:

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

有趣的是, 庆典正确每次检测段错误

Interestingly, bash correctly detects the segfault every time.

我有两个问题:


  1. 任何人都可以解释这种现象?

  1. Can anyone explain this behavior?

任何人都可以提出一个简单的C程序,将可靠段错误在每次执行的?我也曾尝试杀号(getpid(),SIGSEGV),但我得到类似的结果。

Can anyone suggest a simple C program that will segfault reliably on every execution? I have also triedkill(getpid(), SIGSEGV), but I get similar results.


编辑: jbcreix有答案:我段错误检测器被打破。我被愚弄了,因为 KSH 有同样的问题。我试着用庆典庆典右键每次得到它。

jbcreix has the answer: my segfault detector was broken. I was fooled because ksh has the same problem. I tried with bash and bash gets it right every time.

我的错误是,我是路过 WNOHANG waitpid函数(),在那里我应该已经传递零。我不知道我会一直在想!人们不禁要问,什么是 KSH 这件事,但是这是一个单独的问题。

My error was that I was passing WNOHANG to waitpid(), where I should have been passing zero. I don't know what I could have been thinking! One wonders what is the matter with ksh, but that's a separate question.

推荐答案

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

Writing to NULL will reliably segfault or bus error.

有时一个操作系统将一个只读页映射到零地址。因此,你可以有时 NULL 阅读。

Sometimes an OS will map a read-only page to the zero address. Thus, you can sometimes read from NULL.

尽管C定义了 NULL 地址作为特别,那特殊地位'实现'实际上是由操作系统的虚拟内存(​​VM)子系统处理。

Although C defines the NULL address as special, the 'implementation' of that special status is actually handled by the Operating System's Virtual Memory (VM) subsystem.

酒和DOSEMU需要在 NULL 页面映射为Windows兼容。参见 mmap_min_addr等多项 Linux内核重建内核无法做到这一点。

WINE and dosemu need to map a page at NULL for Windows compatibility. See mmap_min_addr in the Linux kernel to rebuild a kernel which cannot do this.

mmap_min_addr等多项是当前的一个热门话题,由于相关的开发,向莱纳斯公共火焰(Linux的名声,很明显),从西奥德若特OpenBSD的努力。

mmap_min_addr is currently a hot topic due to a related exploit and a public flame toward Linus (of Linux fame, obviously) from Theo de Raadt, of the OpenBSD effort.

如果你愿意这样code中的孩子,你可以随时拨打:提高(SIGSEGV);

If you are willing to code the child this way, you could always call: raise(SIGSEGV);

此外,您还可以得到保证到段错误的指针:

为int * ptr_segv = MMAP(NULL,PAGE_SIZE,PROT_NONE,MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS,-1,0);

Also, you can obtain a guaranteed-to-segfault pointer from: int *ptr_segv = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS, -1, 0);

其中, PROT_NONE 的关键在于保留其不能被访问的内存。对于32位Linux的英特尔,PAGE_SIZE为4096。

Where PROT_NONE is the key to reserving memory which cannot be accessed. For 32-bit Intel Linux, PAGE_SIZE is 4096.

这篇关于为什么Linux的程序,derefrences(字符*)0并不总是出现段错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆