我尝试过的所有C编译器都不会在下面的代码片段中检测到未初始化的变量。但是这里的情况很明显。
不要理会此代码片段的功能。这不是真正的代码,因此我将其精简后用于调查此问题。
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 = value ;
收到"local variable 'tauxtrouve' used without having been initialized"
警告。
我尝试了这些编译器:
不初始化此变量的明显性被夸大了。路径分析会花费时间,并且您的编译器供应商要么不想实施该功能,要么认为这会花费您太多时间-或者您只是没有明确选择加入。
例如,使用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.
这些简单示例在执行时间上的差异可以忽略不计。但是,想象一下一个具有数千行,数十个功能,每个都有循环和大量嵌套功能的翻译单元。路径的数量迅速增加,并且成为分析循环中第一次迭代是否在该比较之前进行分配的一个沉重负担。
编辑:@Matthieu指出,对于LLVM / clang,由于IR使用的SSA表示法,随着嵌套的增加,查找未初始化使用的值所需的路径分析不会增加。
它并不-S -emit-llvm
像我希望的那样简单,但是我发现了他描述的SSA注释输出。老实说,我对LLVM IR不够熟悉,但是我会相信Matthieu的话。
底线:clang
与一起使用--analyze
,或说服某人修复该gcc
错误。
; 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
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句