Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
395 views
in Technique[技术] by (71.8m points)

c - Compiler not detecting obviously uninitialized variable

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

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.
}

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

I tried these compilers:

  • GCC 4.9.2 with -Wall -WExtra
  • Microsoft Visual C++ 2013 with all warnings enabled
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

For example, with clang:

$ 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.


EDIT: @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.

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.

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
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...