这个语句的function是什么*(long *)0 = 0;?

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

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

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

但是,像这样的代码常常被用来强制执行分段错误types的崩溃,这有时很方便地放到debugging器中。

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

如果遇到段错误,有时候比在debugging器中手动设置断点更方便。 例如,如果您不使用IDE,那么将这些less数令牌input到所需位置的代码通常比向debugging器提供(文本)命令容易,指定确切的源代码文件和行号手动可以有点烦人。

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

有更好的方法来实现这个目标。 现在许多编译器都有一个固有的(例如,gcc,clang:__ __builtin_trap() ),它产生一个保证引起硬件故障和交付SIGILL的机器指令; 不像未定义的指针技巧,编译器不会优化。 如果你的编译器没有这个function,但是没有assembly插入,你可以手动插入这样一个指令 – 这可能是低级别的代码,以至于额外的机器依赖并不是什么大问题。 或者,你可以叫_exit 。 这可以说是最安全的方式,因为它不会冒险运行信号处理程序,甚至在内部也不涉及函数返回。 但这确实意味着你没有得到核心转储。

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

“if条件X不正确,使程序exception退出”的标准C / C ++习语是assert()macros。 上面的代码会写得更好:

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

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

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

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