取消引用空指针(C / C ++)

时间:2017-09-07 20:11:52

标签: c++ c null

在下面的C / C ++代码中

int * a = malloc(N * sizeof(int)); // suppose return value is NULL
a[2] = 1;

在malloc返回NULL的情况下,我是否保证会发生段错误或行为不可预测?

5 个答案:

答案 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,决定“这是不允许的,所以 代码路径永远不会发生“,并摆脱通常的功能 清理代码;这会导致你的程序滑入任何东西 函数恰好是输出二进制文件的下一个。
  • 如果链接器没有下一个函数但是其他类型的值,它可能会尝试执行那个,这会导致问题,因为它生成了非法指令,或者问题,因为操作系统可能会将其他对象标记为不可执行。
  • 某些嵌入式系统没有虚拟内存,因此实​​际上在内存地址为零时会有一些值,并且很乐意为您提供所需的任何内容。
  • 据我所知,鼻子恶魔需要大多数计算机都没有提供的硬件支持,所以它们不太可能。但是,如果它发生了,不要说你没有被警告。
  • 正如@hvd在评论中指出的那样,编译器可能只是将该行作为死存储库跳过。

如果由于某种原因你想要生成段错误,那么更好的方法是使用

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   诊断信息)。