代码之家  ›  专栏  ›  技术社区  ›  ldog

g++编译器:优化标志添加警告消息

  •  6
  • ldog  · 技术社区  · 16 年前

    我注意到了g++编译器的这种有趣的行为,如果我向编译器添加-o3标志,我会得到

    otsu.cpp:220: warning: ‘x’ may be used uninitialized in this function
    

    但是,当我不使用优化,而是使用调试标志-g时,我根本没有收到任何警告。现在,当-g标志打开时,我更信任编译器;但是,我想知道这是否是应该预期的定义良好的行为?

    为了清楚起见,导致这一点的代码如下:

    int x; //uninitialized
    
    
    getAValueForX( &x ); // function makes use of x,
                         // but x is unitialized
    

    在哪里?

     void getAValueForX( int *x )
     {
         *x = 4;
     }
    

    或者沿着这些线的东西,显然更复杂。

    7 回复  |  直到 16 年前
        1
  •  16
  •   Kyle Butt    16 年前

    这是意料之中的。优化会导致运行特定的代码分析,这就是GCC查找未初始化变量的方式。在手册页上:

    . …这些警告取决于优化

    http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

        2
  •  3
  •   PierreBdR    16 年前

    这实际上与GCC非常相似。是的,这是意料之中的。

    据我所知,为了进行优化,编译器生成了大量的度量并转换代码(或者更准确地说,它对代码的表示),以允许检测示例中未初始化或未使用的变量(还有其他一些类似的警告,我不记得列表)。

    在没有优化的情况下做同样的事情需要做,然后放弃所有这些分析。这将大大降低编译速度,但目的并不好(特别是在调试过程中,编译器不需要重新排列代码)。

        3
  •  3
  •   Clifford    16 年前

    优化程序执行的代码流分析允许它检测正常(更快)编译无法检测到的潜在问题。问题总是存在的,编译器只是没有检查它。

    即使发出此警告,实际上也可能不是问题,因为实际使用函数;编译器将假定其参数类型的所有可能值(以及函数中使用的任何外部变量)可能出现在所有可能的组合中-导致至少一个使用变量的路径没有赋值。您的实际使用将有一组更严格的可能状态,因此在实践中可能永远不会出现这种路径。简单的解决方案就是初始化变量,如果只是关闭编译器的话——这不会给您带来任何损失。

    我总是使用乐观主义者作为穷人静态分析的一种形式,即使我最终不打算在生产代码中使用它。同样,我经常出于同样的原因使用多个编译器。有些编译器执行其他编译器不执行的检查,或者为相同的错误生成不同的措辞的消息,这通常有助于解释某些较为迟钝的消息。

    报价:

    当-g 标志已打开

    虽然对于像gcc这样的成熟编译器来说,如果编译器有一个bug,它很可能是在优化程序中(它是最复杂的部分),这是一个非常罕见的发现。相反,人们经常发现他们的工作代码在优化时失败;大多数情况下,代码总是有缺陷(可能它依赖于未定义的或编译器定义的行为),而优化者刚刚暴露了这个缺陷。所以我建议如果你发现你的代码在优化中被破坏,在编译器-occam's razor应用之前怀疑代码。

        4
  •  1
  •   Notinlist    16 年前

    我的编译器标志:

    CFLAGS=-W -Wall\
     -Wno-non-template-friend\
     -Wold-style-cast\
     -Wsign-promo\
     -Wstrict-null-sentinel\
     -Woverloaded-virtual
    # -Weffc++
    

    -weffc++真的很烦人,所以有时我会尝试它,但一般情况下我会把它关闭。 试试这些-还有手册中的其他-让我们看看我们看到了什么。

        5
  •  1
  •   Dan Moulding    16 年前

    是的,这是定义明确的行为。当gcc的优化器未启用时,它不会执行某些类型的执行路径检查(以避免执行这些类型检查的性能损失)。某些情况,例如使用未初始化的变量,只能在执行这些额外检查时检测到。因此,随着 -O0 ,GCC无法警告这些情况。

        6
  •  1
  •   bahree    16 年前

    好吧,编译器可以四处移动以进行优化这一事实可能会导致问题并导致未定义的行为(如下面的手册所述);我认为看到代码来尝试并帮助理解是很有帮助的。

    优化代码的快捷方式 偶尔会产生惊喜 结果:您声明的一些变量 可能根本不存在;控制流 可能会暂时移到你没有的地方 期待;有些陈述可能不是 执行是因为它们计算常量 结果或其值已经 手头;一些语句可能执行 在不同的地方,因为他们 从循环中移出。

        7
  •  0
  •   EvilTeach    16 年前

    我的MSVC 6编译器也有同样的问题。初始化有问题的变量,从编译器的角度消除了错误路径的可能性。