C++ 这个语句*(长*)0=0;的功能是什么;?

C++ 这个语句*(长*)0=0;的功能是什么;?,c++,c,C++,C,在下面的代码中,*(long*)0=0与if子句一起使用,但它的用途是什么 if(r.wid*r.ht < tot) *(long*)0=0; if(r.wid*r.ht

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

if(r.wid*r.ht < tot)
    *(long*)0=0;
if(r.wid*r.ht
它写入0到0,解释为
的地址,即
NULL
指针。这样做是无效的,因为
NULL
从来都不是一个您可以有效地拥有程序可以访问的数据的地址。此代码触发未定义的行为;一般来说,你不能依靠它来产生任何特定的效果

然而,像这样的代码通常被用来强制类型崩溃,这有时很方便放入调试器中

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


如果您得到一个segfault,用这种方式触发它有时比在调试器中手动设置断点更方便。例如,如果您不使用IDE,在所需位置将这些标记键入代码通常比向调试器发出(文本)命令更容易,手动指定确切的源代码文件和行号可能有点烦人。

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

若要使程序“异常退出”,请使用
abort()
函数()

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

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

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


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

为什么保证这个代码会导致分段错误?有没有理由支持这个方法而不是断言?@Zaibis C99草案说“如果指针被赋值无效,一元
*
操作符的行为是未定义的”,虽然@unwind的答案对于大多数通用机器来说是完全正确的(他正确地指出这是未定义的行为,并且不能保证),但这种代码确实在嵌入式系统中找到了位置,在那里确实存在一些东西(内存映射IO或专用内存地址)在地址0处(或空指针映射到的任何地址)。@Damon在我倾向于处理的庞大代码库中,我们倾向于在发布版本中启用尽可能多的断言,因为实际上不可能确保您不能通过某些代码路径命中它们,可能,尽管QA和测试开发付出了最大的努力,但还是被遗漏了。此语句应该是一个带有描述性名称的宏。(这是使用宏的少数几个好理由之一。您希望崩溃发生在正确的函数中,以便堆栈帧有意义)C++还是C?我没有看到任何C++特性,但是标准可能不同。你真的尝试过吗?上次我这么做时,我的编译器只是省略了整个语句。根据C标准,这是完全合法的。现代编译器可能会删除整段代码。
then
部分是未定义的行为,因此编译器可以假定它是不可访问的。假设
if
表达式没有副作用,则可以删除整个
if
语句。Redis使用类似的技巧模拟seg故障,然后您可以在调试器中从中提取,请参阅。正如我在回答相关问题时所说,这是未定义的行为,如果在某些情况下对其进行了优化,我也不会感到惊讶。前一个线程也是恰当的。它是一个答案;这不是你想要的有用的答案。但这并不是说这是一个非答案的理由。这是程序的缩进,但不一定是它实际做的。这个
assert( r.wid*r.ht >= tot );