【发布时间】:2017-05-11 01:54:37
【问题描述】:
免责声明:
- 我在这里分享的代码是真实代码的独立版本,但会重现相同的行为。
以下代码使用 gcc 5.4.0 编译并在 Ubuntu 16.04 上启用优化,执行时会生成无限循环:
#include <stdio.h>
void *loop(char *filename){
int counter = 10;
int level = 0;
char *filenames[10];
filenames[0] = filename;
while (counter-- > 0) {
level++;
if (level > 10) {
break;
}
printf("Level %d - MAX_LEVELS %d\n", level, 10);
filenames[level] = filename;
}
return NULL;
}
int main(int argc, char *argv[]) {
loop(argv[0]);
}
编译器版本:
gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
使用的编译命令:
gcc infinite.c -O2 -o infinite
我知道这是由优化标志“-02”引起的,因为没有它就不会发生。我也知道将 volatile 添加到变量“level”也可以修复错误。但我不能将此关键字添加到我的所有变量中。
我的问题是,为什么会发生这种情况,我以后可以做些什么来避免它?
是否有任何 gcc 标志仍然在 -O2 的类似级别上优化代码而没有此类问题?
【问题讨论】:
-
您的行为未定义,因为
filenames[level] = filename;可以访问无效内存,因为level可以是10。 -
正如其他人所说,文章的标题应该是“错误的程序导致无限循环”。当程序调用未定义的行为时,所有行为都是“正确的”。
-
从 loop() 返回 NULL,但从 main() 调用 loop() 函数从不分配返回值 - 这对 UB 有影响吗?还是这只是被遗忘的返回值?
-
@Nguaial 不同版本的编译器使用不同的优化策略。对于 GCC,通常版本号越高,优化完成的越多或做得越好。
-
是否修改代码使
if (level > 10)更改为if (level > 9)解决问题?
标签: c gcc optimization