这个陈述的功能是什么*(长*)0 = 0;?

时间:2014-01-27 08:59:52

标签: c++ c

在以下代码中,*(long*)0=0;if子句一起使用,但其目的是什么?

if(r.wid*r.ht < tot)
    *(long*)0=0;

4 个答案:

答案 0 :(得分:58)

将0写入0解释为long的地址,即NULL指针。这不是一件有效的事情,因为NULL永远不是一个可以有效获取程序可以访问的数据的地址。此代码触发未定义的行为;一般来说,你不能依靠它产生任何特殊的效果。

但是,通常使用这样的代码强制segmentation fault - 类型崩溃,这有时很容易放入调试器。

同样,这是未定义的行为;不能保证它会导致这样的错误,但是在有分段错误的系统上,上面的代码很可能产生一个错误。在其他系统上,它可能会做一些完全不同的事情。

如果你得到一个段错误,有时候通过这种方式触发比在调试器中手动设置断点更方便。例如,如果您没有使用IDE,那么将这些少量令牌输入到所需位置的代码中往往比向调试器提供(textual)命令更简单,指定确切的源代码文件和行号手动可能有点烦人。

答案 1 :(得分:18)

在教科书C中,abort是故意使程序崩溃的方法。但是,当您在接近金属编程时,您可能不得不担心abort无法按预期工作! abort的标准POSIXy实现调用getpidkill(通过raise)将SIGABRT传递给进程,进而可能导致执行信号处理程序,可以随心所欲。有些情况,例如在malloc的内心深处,为了应对灾难性的,可能是对抗性的内存损坏,你需要在不触及堆栈的情况下强制崩溃(具体而言,不执行可能跳转到恶意代码的返回指令) )。 *(long *)0 = 0在这种情况下尝试并不是最疯狂的事情。它仍然存在执行信号处理程序的风险,但这是不可避免的;没有进行函数调用就无法触发SIGKILL。更严重的(恕我直言)现代编译器有点太可能看到它,观察它有未定义的行为,删除它,并删除测试,因为测试不可能是真的,因为没有人会故意调用未定义的行为,是吗?如果这种逻辑看起来有悖常理,请阅读LLVM小组的discourse on undefined behavior and optimizationpart 2part 3)。

有更好的方法来实现这一目标。现在许多编译器都有一个内在的(例如gcc,clang:__builtin_trap()),它生成一个机器指令,保证导致硬件故障并传递SIGILL;与使用指针的未定义技巧不同,编译器不会优化它。如果您的编译器没有那个,但确实有汇编插入,那么您可以手动插入这样的指令 - 这可能是低级别的代码,以至于额外的机器依赖性并不是什么大问题。或者,您可以致电_exit。这可以说是最安全的方式,因为它不会冒着运行信号处理程序的风险,并且即使在内部它也不涉及函数返回。但这确实意味着你没有获得核心转储。

答案 2 :(得分:6)

要使程序“异常退出”,请使用abort()函数(http://pubs.opengroup.org/onlinepubs/9699919799/functions/abort.html)。

“如果条件X不为真,使程序异常退出”的标准C / C ++习语是assert()宏。上面的代码会写得更好:

assert( !(r.wid*r.ht < tot) );

或(如果您乐意忽略边缘情况),它会更清晰地读取:

assert( r.wid*r.ht >= tot );

答案 3 :(得分:3)

如果r的宽度乘以高度小于总数,则使程序崩溃。