【发布时间】:2017-05-09 03:16:42
【问题描述】:
在为code golf 比赛编写代码时,我注意到一些奇怪的行为。例如:
int main(void)
{
goto jmp;
char *str = "Hello, World!";
jmp:
puts(str);
}
使用 GCC(以及 Clang 和 MSVC)编译不会产生警告或错误,但运行它会抛出 SIGSEGV。为什么编译器没有发现 goto 正在跳转变量声明?
我决定对此(错误?)进行测试,并重写示例:
int main(void)
{
goto jmp;
int x;
jmp:
putchar(x);
}
同样,编译不会产生错误。此外,执行时不会抛出任何内容,但在 MSVC 中,进程以非零退出代码退出。
这里发生了什么?这仅仅是我们不应该使用gotos 的另一个原因吗?为什么第二个例子没有抛出错误,而第一个例子抛出了SIGSEGV?
【问题讨论】:
-
这是未定义的行为。您已跳过变量声明,稍后尝试使用它。甚至尝试这样做有什么意义?你期待什么样的结果?
-
这不是编译器的工作。
-
@InternetAussie OP 提到他在打代码打高尔夫球。也许是为了this 挑战?
-
@MDXF 也许,但任何事情都不应该依赖未定义的行为。除非您知道特定编译器和实现如何处理它的详细信息,否则应该避免未定义的行为。
-
我在 ubuntu gcc 5.4.0 上编译,带有标志
-Wall -Wextra -pedantic。没有错误,但是有一个警告`warning: 'str' is used uninitialized in this function [-Wuninitialized]`。
标签: c gcc clang goto segmentation-fault