当Cppcheck运行此代码时, [1] 它会抱怨错误:
void bool_express(bool aPre, bool aX, bool aPost)
{
bool x;
const bool pre = aPre;
if (pre) {
x = aX;
}
const bool post = aPost;
// error checking passage of the original code:
if ( !pre || !x || !post ) {
if ( !pre ) {
trace("pre failed");
} else if ( !x ) { // <-- HERE Cppcheck complains
trace("x failed");
} else {
trace("post failed");
}
} else {
// success passage of the original code:
trace("ok");
}
}
这是让我紧张的信息:
Id: uninitvar
Summary: Uninitialized variable: x
Message: Uninitialized variable: x
我认为这是误报,但我承认这可能并不明显。尽管如此,我还是不想触摸那段代码,因为它比这个提取的版本更古老,更重。
您是否经历过这样的情况?怎么处理呢?
[1] 此代码简化为骨骼,原始代码建立前提条件(pre
),执行某些操作(x
),然后强制后置条件( post
)之后,检查一些错误条件。我将所调用函数的运行时结果转换为pre
,x
和post
中存储到我的测试用例的3个参数中。
答案 0 :(得分:1)
静态分析似乎在抱怨,因为如果runMaybeT
为false,则永远不会设置pre
。
您的代码的结构使得x
为假时永远不会访问x
的值 - 我认为静态分析器不是&#39;在这种情况下给出一个有用的输出。
列举我们拥有的各种案例(因此我们可以合理地确定它是cppcheck而不是我们!):
访问pre
的第一个语句位于x
行 - 由于short-circuiting evaluation:if ( !pre || !x || !post )
并未评估{{1}如果if( A || B || C )
为真,则为B
;因此,我们永远不会尝试阅读未初始化的C
(因为A
仅在x
为假时未被初始化,在这种情况下我们停止评估表达式!)
第二种用法是
x
同样,如果pre
为真,我们只能触及有问题的行(在这种情况下if ( !pre ) {
trace("pre failed");
} else if ( !x ) { // <-- HERE Cppcheck complains
已正确初始化)。
由此,我们可以得出结论:
实际代码在某种情况下错误地尝试阅读pre
,即使x
为假,在构建示例时您也错过了它(有时是逻辑流程程序可能有点迟钝)
静态分析器是惰性的并且会找到行x
,并且无法确定此行是否可以使用未初始化的值进行访问。
根据您提供的代码,您不应该担心:静态分析工具在技术上是正确的,pre
可以是未初始化的,但在这些情况下它不会被使用(因此可能不应该警告你)。
如果您不自信,或者实际逻辑非常钝,我建议您为else if( !x )
分配一个默认值。
答案 1 :(得分:1)
Cppcheck中的误报。我通过添加内联抑制来解决: [1]
if ( !pre ) {
trace("pre failed");
// cppcheck-suppress uninitvar
} else if ( !x ) {
trace("x failed");
} else {
trace("post failed");
}
我也引起了Cppcheck开发人员的注意:
#7663 (False positive: uninitialised variable in unreachable code)
[1] 我决定不初始化变量。这不是出于性能原因,而是为了了解未来版本中修复的错误,当时Cppcheck会说
Id: unmatchedSuppression
Summary: Unmatched suppression: uninitvar
Message: Unmatched suppression: uninitvar
答案 2 :(得分:0)
如果您的pre
条件为false
,则x将未初始化。在第if ( !x )
行,CppCheck警告使用不确定值。要修复它,请初始化x
变量。