编译器检测不到明显未初始化的变量 [英] Compiler not detecting obviously uninitialized variable

查看:421
本文介绍了编译器检测不到明显未初始化的变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所有的C编译器我试过在下面的code段将不检测未初始化的变量。然而,情况很明显这里。

All C compilers I've tried won't detect uninitialized variables in the code snippet below. Yet the case is obvious here.

不要理会这个片段的功能。这不是真正的code和我剥离下来对这个问题进行调查。

Don't bother about the functionality of this snippet. It's not real code, and I stripped it down for the investigation of this issue.

BOOL NearEqual (int tauxprecis, int max, int value)
{
  int tauxtrouve;      // Not initialized at this point
  int totaldiff;       // Not initialized at this point

  for (int i = 0; i < max; i++)
  {
    if (2 < totaldiff)  // At this point totaldiff is not initialized
    {
      totaldiff = 2;
      tauxtrouve = value;  // Commenting this line out will produce warning
    }
  }

  return tauxtrouve == tauxprecis ;  // At this point tauxtrouve is potentially
                                     // not initialized.
}

在另一方面,如果我注释掉 tauxtrouve =值; ,我得到的没有初始化就使用局部变量tauxtrouve 警告。

On the other hand, if I comment out tauxtrouve = value ;, I get the "local variable 'tauxtrouve' used without having been initialized" warning.

我想这些编译:


  • GCC 4.9.2 与-Wall -Wextra

  • 微软的Visual C ++ 2013的所有警告启用

  • GCC 4.9.2 with -Wall -WExtra
  • Microsoft Visual C++ 2013 with all warnings enabled

推荐答案

与此变量没有被初始化被夸大了的显而易见。路径分析花费时间和您的编译器厂商既没有要实现的功能,或者认为它会花费你太多的时间 - 或者你只是没有明确地选择加入

The obviousness with which this variable is not initialized is overstated. Path analysis costs time and your compiler vendors either didn't want to implement the feature or thought it would cost you too much time -- or you just didn't explicitly opt-in.

例如,用

$ clang -Wall -Wextra -c obvious.c 
$ clang -Wall -Wextra --analyze -c obvious.c 
obvious.c:9:11: warning: The right operand of '<' is a garbage value
    if (2 < totaldiff)  // at this point totaldiff is not initialized
          ^ ~~~~~~~~~
obvious.c:16:21: warning: The left operand of '==' is a garbage value
  return tauxtrouve == tauxprecis ;  // at this point tauxtrouve is potentially
         ~~~~~~~~~~ ^
2 warnings generated.

有这些天真实施例中的执行时间的差异是可以忽略不计。但是想象一下,一个翻译单元数千行,数万功能,每个循环和重嵌套。的路径的数量迅速化合物和成为大的负担通过循环来分析是否在第一次迭代的分配是否将在此之前,比较发生

The difference in execution time for these naïve examples is negligible. But imagine a translation unit with thousands of lines, tens of functions, each with loops and heavy nesting. The number of paths quickly compounds and becomes a large burden to analyze whether or not the first iteration through the loop whether the assignment will occur prior to that comparison.

编辑:@Matthieu指出,与LLVM /铛,发现未初始化的用的价值不加剧,因为红外线使用的SSA符号作为嵌套的增加所需要的路径分析

@Matthieu points out that with LLVM/clang, the path analysis required to find use-of-uninitialized value does not compound as nesting increases because of the SSA notation used by the IR.

这是不是那样简单 -S -emit-LLVM 像我所希望的,但我发现他描述了SSA-符号输出。我会说实话,我不熟悉不够用LLVM IR可以肯定的,但我会采取马蒂厄的话吧。

It wasn't as simple as "-S -emit-llvm" like I'd hoped, but I found the SSA-notation output he described. I'll be honest, I'm not familiar enough with LLVM IR to be sure, but I'll take Matthieu's word for it.

底线:使用 - 分析,或说服别人来修复 GCC 错误。

Bottom line: use clang with --analyze, or convince someone to fix the gcc bug.

; Function Attrs: nounwind uwtable
define i32 @NearEqual(i32 %tauxprecis, i32 %max, i32 %value) #0 {
  br label %1

; <label>:1                                       ; preds = %7, %0
  %tauxtrouve.0 = phi i32 [ undef, %0 ], [ %tauxtrouve.1, %7 ]
  %i.0 = phi i32 [ 0, %0 ], [ %8, %7 ]
  %2 = icmp slt i32 %i.0, %max
  br i1 %2, label %3, label %9

; <label>:3                                       ; preds = %1
  %4 = icmp slt i32 2, 2
  br i1 %4, label %5, label %6

; <label>:5                                       ; preds = %3
  br label %6

; <label>:6                                       ; preds = %5, %3
  %tauxtrouve.1 = phi i32 [ %value, %5 ], [ %tauxtrouve.0, %3 ]
  br label %7

; <label>:7                                       ; preds = %6
  %8 = add nsw i32 %i.0, 1
  br label %1

; <label>:9                                       ; preds = %1
  %10 = icmp eq i32 %tauxtrouve.0, %tauxprecis
  %11 = zext i1 %10 to i32
  ret i32 %11
}

这篇关于编译器检测不到明显未初始化的变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆