关于c ++:为什么goto的宏定义会使程序崩溃?

Why this macro define of goto will crash the program?

我在读一篇文章,在其中一个答案中有以下代码

1
#define goto { int x = *(int *)0; } goto

在这里作者指出,每当一个人试图使用goto语句时,他的程序就会崩溃,我的问题是为什么?根据我的理解,int x = *(int *)0;将内存地址前4个字节中的任何内容分配给x,但为什么这肯定会使程序崩溃?


只是因为您正在取消对NULL指针的引用。但是程序崩溃的定义还没有确定。它可能会崩溃,可能不会崩溃或者做一些奇怪的事情。这只是一种不明确的行为,最好避免。

值得注意的是,goto并没有那么无用。每一个关键词都有自己的位置,语言作者和标准委员会的成员有理由继续保持它(考虑到语言正在发生一些巨大的变化)。如果明智地使用,Goto在C和C++中有一个适当的位置。

Just to give an idea how this is an UB, using VC11, I compiled the
above snippet in debug and release mode. In debug mode it crashed but
in release mode, compiler simply optimized out the statement and there
was no crash.

号


该代码在两个方面给出了未定义的行为。

首先,重新定义语言关键字本身会产生未定义的行为。

第二,正如其他人所说,值为"0"的指针是空指针,取消对它的引用会给出未定义的行为。

因此,构造的实际结果是未定义的行为。未定义行为的一个常见症状是程序崩溃。然而,实际上并不能保证撞车。它甚至不是必需的。

作为"为什么?"在编写宏的过程中,该代码的作者显然是"Goto is Evil"阵营的订阅者,他/她认为自己适合任意地对他人施加他/她的未成形的偏见。实际上,即使替代方案通常更可取,goto也有其用途。即使是Dijkstra(原稿的作者,人们经常引用它来证明不使用goto)也只描述了自由使用的问题,并没有声称应该简单地避免使用。DonaldKnuth后来在70年代中期写了一篇关于这个主题的论文,包括使用goto是有益的例子。


在C或C++中,内存地址0表示空指针。取消对此类指针的引用总是未定义的行为,在大多数实现中,它会引发分段错误,从而有效地"破坏"程序。