关于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表示空指针。取消对此类指针的引用总是未定义的行为,在大多数实现中,它会引发分段错误,从而有效地"破坏"程序。