在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?