GCC-没有关于带有-O0的未初始化数组的警告

时间:2018-08-02 17:25:28

标签: c gcc

我的GCC 7.3.0和8.2.0有一些我无法解释的奇怪行为。 该程序显然以Segmentation错误结束:

int main()
{
    double array[2]={0, 0};
    printf("%f\n", array[999]);

    return 0;
}

编译为

gcc -Wall -O2 main.c

产生警告

main.c: In function 'main':
main.c:6:5: warning: 'array[999]' is used uninitialized in this function [-Wuninitialized]
     printf("%f\n", array[999]);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~

但是关闭了优化功能

gcc -Wall main.c

它完全不发出警告。 我的代码linter和Debug编译(gcc -g)使用-O0,并且没有遇到类似的超出范围的错误,直到我将其编译为“打开并启用优化”。在linter中设置-O1会按预期发布警告。

1 个答案:

答案 0 :(得分:4)

这是GCC中长期存在的记录限制。引用manual for GCC 3.0

  

-Wuninitialized

     

警告是否使用了未先初始化的自动变量,或者是否可能被setjmp调用破坏了。

     

这些警告仅在优化编译时才可能出现,因为它们需要仅在优化时才计算的数据流信息。如果未指定-O,则只会收到这些警告。

current version of the manual实际上删除了引号的第二段,而是说:“由于这些警告取决于优化,因此警告的确切变量或元素取决于精确的优化选项和所使用的GCC版本”。这是因为,在GCC 3.0(2001年发布)和GCC 8.2(2018年发布)之间的某个时刻,对编译器进行了改进,以便在不进行优化时,至少对某些未初始化变量的使用给出警告。例如,琐碎的测试

int foo(void) { int x; return x; }

在使用-O0 -Wall的GCC 8.2编译时会引发警告。

值得指出的是,对未初始化变量的 perfect 诊断可以减少到臭名昭著的Halting Problem,这意味着它无法完成。您可以实施一系列保守地正确的规则(它们将检测未初始化变量的所有使用,但它们可能会声称某些变量在未初始化时未使用),例如Java的definite assignment规则,但是这种方法历来在C程序员中并不受欢迎。考虑到需要最小的误报,但在不进行优化时也需要快速编译的要求,因此可以理解,GCC在优化启动时进行更精细分析的方法是可以理解的。