在下面的C / C ++代码中
int * a = malloc(N * sizeof(int)); // suppose return value is NULL
a[2] = 1;
在malloc返回NULL
的情况下,我是否保证会发生段错误或行为不可预测?
答案 0 :(得分:10)
总之,没有。
引用Wikipedia:
取消引用NULL指针通常会导致尝试读取 或者从未映射的内存中写入 - 触发分段 故障或访问冲突。这可能代表开发人员 作为程序崩溃,或被转换为可以的异常 抓住。 然而,在某些情况下,这不是 案例。例如,在x86-real模式下,地址0000:0000是 可读且通常可写,因此取消引用空指针 一种完全有效但通常不需要的行为,可能导致 应用程序中未定义但非崩溃的行为。另请注意 有时取消引用NULL是有意的 并且定义明确;例如,用C语言编写的用于16位的BIOS代码 实模式x86设备可以在物理地址0处写入IDT 通过取消引用NULL指针进行写入。 也是 编译器可以优化掉
NULL
指针 取消引用,避免分段错误但导致其他不需要的 行为强> ...在C中,取消引用空指针的行为是undefined。
另请查看此wild example空引用的空类指针,但仍然可以正常工作。
基本上,不要这样做,但是你知道:)
答案 1 :(得分:5)
C标准保证
取消引用无效指针会调用undefined behavior。
答案 2 :(得分:3)
您没有任何保证;取消引用空指针是undefined behavior。它会可能导致段错误,除非你打开某些优化或者在一个奇怪的平台上进行编译,在这种情况下它可能会开始执行一些其他有效随机参数的函数,产生一些其他错误,抓住一些内存值,或make demons fly out of your nose,或完全跳过该行。只有 其中一个我甚至会惊讶的是倒数第二个。
更详细:
NULL
,决定“这是不允许的,所以
代码路径永远不会发生“,并摆脱通常的功能
清理代码;这会导致你的程序滑入任何东西
函数恰好是输出二进制文件的下一个。如果由于某种原因你想要生成段错误,那么更好的方法是使用
kill(getpid(), SIGSEGV);
(包括适当的标题后)。这会发送段错误信号而不会发生任何实际的分段违规。如果您确实希望实际提交分段违规,您最好选择映射然后取消映射某些页面(这取决于操作系统),然后尝试访问指向该页面的指针。< / p>
答案 3 :(得分:1)
不,不能保证。
例如,如果您在示例之前运行此(邪恶)代码该怎么办:
mmap( ( void *) 0, ( size_t ) 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0 );
映射具有地址0
的读/写权限的匿名页面。
答案 4 :(得分:1)
不,该程序不保证会出现段错误。已为Dereferencing a pointer分配了无效值的undefined behaviour,标准明确指出未定义的行为不会产生任何要求。它可以终止程序执行,但它不必;它甚至可能完全忽略这种情况:
3.4.3未定义的行为
1个行为,在使用不可移植或错误的程序构造时 或者本国际标准没有规定的错误数据 要求
2注意可能的未定义的行为包括忽略这种情况 完全,结果不可预测,在翻译过程中表现出色 或者以文件化的方式执行程序 环境(有或没有发出诊断信息),到 终止翻译或执行(发布a 诊断信息)。