错误代码+ GCC 5.4优化导致无限循环

Thi*_*ago 2 c optimization gcc

免责声明:

  • 我在这里分享的代码是真实代码的独立版本,但是重现了相同的行为.

以下使用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]);
}
Run Code Online (Sandbox Code Playgroud)

编译器版本:

gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
Run Code Online (Sandbox Code Playgroud)

使用的编译命令:

gcc infinite.c -O2  -o infinite
Run Code Online (Sandbox Code Playgroud)

我知道它是由优化标志"-02"引起的,因为没有它就不会发生.我也知道将volatile添加到变量"level"也可以修复错误.但我无法将此关键字添加到我的所有变量中.

我的问题是,为什么会发生这种情况,我可以做些什么来避免将来呢?

是否有任何gcc标志仍然在类似的-O2级别优化代码而没有这种问题?

use*_*751 6

您已经找到了一个未定义行为的示例,导致优化器执行意外操作!GCC可以看到,如果循环运行10次,则存在未定义的行为.

这段代码将filenames[1]通过,filenames[10]即第2到第11个元素来写filenames.但是filenames10个元素长,所以最后一个是未定义的行为.

因为你不允许有未定义的行为,所以它可以假设循环在它到达10之前会以其他方式停止(也许你有一个修改过的版本printf会调用exit?).

并且它看到如果循环在它到达10之前仍然会停止,那么没有必要让代码只运行10次.所以它删除了该代码.