在C中产生Segfault的最简单的标准符合方式是什么?

我认为这个问题说明了一切。 涵盖从C89到C11的大多数标准的例子会很有帮助。 我虽然这一个,但我想这只是未定义的行为:

#include <stdio.h>

int main( int argc, char* argv[] )
{
  const char *s = NULL;
  printf( "%cn", s[0] );
  return 0;
}

编辑:

正如一些投票要求澄清的那样:我想要一个有通常编程错误的程序(我能想到的最简单的就是一个段错误),这是保证(通过标准)中止。 这与最小的段落问题有些不同,它不关心这种保险。


分段错误是实现定义的行为。 该标准没有定义实现如何处理未定义的行为,实际上实现可以优化未定义的行为并仍然符合规范。 要明确的是,实现定义的行为是标准中没有指定的行为,但实现应该记录下来。 未定义的行为是不可移植或错误的代码,其行为是不可预测的,因此不能被依赖。

如果我们看看C99草案标准§3.4.3未定义的行为,它在第1段中的术语,定义和符号部分中说明了(重点是我的前进):

行为,在使用不可移植或错误的程序结构或错误数据时, 本国际标准对此没有要求

并在第2段中说:

注意可能存在未定义的行为范围,包括忽略完全不可预知的结果,在翻译或程序执行期间以文档化的方式表现环境特性(无论是否发布诊断消息),终止翻译或执行(使用发布诊断消息)。

另一方面,如果你只是想要一个在标准中定义的方法,在大多数类Unix系统上会导致分段错误,那么raise(SIGSEGV)应该实现这个目标。 严格地说,尽管SIGSEGV的定义如下:

SIGSEGV无法访问存储

和§7.14信号处理<signal.h>说:

一个实现不需要生成任何这些信号,除非由于显式调用raise函数 。 额外的信号和指向无声函数的指针,宏定义分别以字母SIG和大写字母或SIG_和大写字母开头,219)也可以由实现指定。 完整的信号集,它们的语义以及它们的默认处理是实现定义的 ; 所有的信号数量应为正值。


raise()可用于引发段错误:

raise(SIGSEGV);

该标准只提到未定义的行为。 它对内存分段一无所知。 另请注意,产生错误的代码不符合标准。 您的代码无法调用未定义的行为,并且同时符合标准。

尽管如此,在产生这种故障的体系结构上产生分段错误的最短途径是:

int main()
{
    *(int*)0 = 0;
}

为什么这肯定会产生段错误? 因为访问内存地址0总是被系统捕获; 它永远不会是一个有效的访问(至少不是用户空间代码)。

当然,并不是所有的架构都以相同的方式工作。 在其中的一些上面,上述不会崩溃,而是产生其他类型的错误。 或者声明可能非常好,甚至可以访问内存位置0。 这是标准没有真正界定发生的原因之一。

链接地址: http://www.djcxy.com/p/43875.html

上一篇: What is the simplest standard conform way to produce a Segfault in C?

下一篇: What is a segmentation fault?