声明:
以下使用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级别优化代码而没有这种问题?
答案 0 :(得分:6)
您已找到一个未定义行为的示例,导致优化器执行意外操作! GCC可以看到,如果循环运行10次,则存在未定义的行为。
此代码将filenames[1]
写入filenames[10]
,即filenames
的第2到第11个元素。但是filenames
长度为10个元素,因此最后一个是未定义的行为。
因为不允许你有未定义的行为,所以它可以假设循环在它到达10之前会以其他方式停止(也许你有printf
的修改版本会调用{{1} }?)。
它看到如果循环在到达10之前仍然会停止,那么没有必要让代码只运行10次。所以它删除了那段代码。