绊倒在C ++中的非凡布尔场景中 [英] stumbling upon a non-trivial bool scenario in C++
问题描述
当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;
//错误检查原始代码的通过:
if(!pre ||!x ||!post){
if(!pre){
trace( pre failed);
}否则if(!x){//<-Cppcheck在这里抱怨
trace( x failed);
}否则{
trace( post failed);
}
} else {
//成功通过原始代码:
trace( ok);
}
}
这是一条消息,让我感到紧张:
Id:uninitvar
摘要:未初始化变量:x
消息:未初始化变量:x
我认为这是一个误报,但我承认这可能并不明显。不过,我不想修改该代码,因为它比此提取的版本旧且重得多。
您是否遇到过这种情况?如何处理它?</ p>
[1] 这段代码精简了,原始代码建立了前提条件( pre
),做了一些事情( x
),然后强制了后置条件( post
),然后检查一些错误情况。我转换了所调用函数的运行时结果,然后将其存储在 pre
, x
和 post
放入测试用例的3个参数中。
静态分析似乎之所以抱怨,是因为如果 pre
为假,则永远不会设置 x
。
您的代码的结构使得如果 pre
为<$>,则永远不会访问 x
的值错误-在这种情况下,我认为静态分析器无法提供有用的输出。
枚举我们遇到的各种情况(因此我们可以可以合理地确定它是cppcheck而不是我们!):
-
其中
x
在if(!pre ||!x ||!post)
行中-由于短路评估:if(A || B || C)
不评估B
或C
,如果A
为真;因此,我们绝不会尝试读取未初始化的x
(因为x
仅在pre
为假,在这种情况下,我们停止了对表达式的求值!) -
第二种用法在
中
if(!pre){
trace( pre failed);
}否则,如果(!x){//<-Cppcheck在这里抱怨
我们只能再次点击如果
pre
为真(在这种情况下x
已正确初始化),则违反了代码。
由此,我们可以得出以下结论:
-
实际代码在某些情况下错误地尝试读取
x
,即使pre
是错误的,并且您已经构建示例时错过了它(有时程序的逻辑流程可能有点钝) -
静态分析器很懒,并且发现行
else if(!x)
,并且无法确定该行是否可以通过未初始化的值访问。
从您提供的代码中,您不必担心:静态分析工具在技术上是正确的,可以对 x
进行初始化,但是在这种情况下,它不会被使用(因此可能不应该警告您)。
如果您不确定或实际逻辑过于晦涩,可为 x
分配一个默认值。
When Cppcheck runs over this code,[1] it complains about an error:
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");
}
}
This is the message, that makes me nervous:
Id: uninitvar
Summary: Uninitialized variable: x
Message: Uninitialized variable: x
I think it's a false positive, but I admit that this may not be obvious. Nevertheless I don't want to touch that code, because it's old and a lot heavier than this extracted version.
Have you ever experienced situations like this? How to deal with it?
[1] This code is reduced to its bones, the original code establishes a precondition (pre
), does something (x
), then forces a postcondition (post
), after that, some error conditions are checked. I transformed the runtime-results of the functions that are called and then stored in pre
, x
, and post
into the 3 arguments of my test case.
The static analysis appears to be complaining because if pre
is false, then x
is never set.
Your code is structured such that the value of x
is never accessed if pre
is false - I'd argue that the static analyser isn't giving a useful output in this case.
Enumerating the various cases we have (so we can be reasonably sure that it's cppcheck and not us!):
The first statement in which
x
is accessed is in the lineif ( !pre || !x || !post )
- due to short-circuiting evaluation:if( A || B || C )
doesn't evaluateB
orC
ifA
is true; hence we never try to read an uninitialisedx
(sincex
is only uninitialised ifpre
is false, in which case we stopped evaluated the expression!)The second usage is in
if ( !pre ) { trace("pre failed"); } else if ( !x ) { // <-- HERE Cppcheck complains
Again, we can only hit the offending line if
pre
was true (in which casex
is properly initialised).
From this, we can conclude that either:
The actual code mistakenly tries to read
x
in some condition even ispre
is false, and you've missed it when building the example (sometimes the logical flow of a program can be a bit obtuse)The static analyser is lazy and spots the line
else if( !x )
and can't determine if this line is reachable with an uninitialised value.
From the code you've provided, you shouldn't be concerned: the static analysis tool is technically correct that x
can be uninitialised, but in those cases it's not used (and hence probably shouldn't be warning you).
I'd recommend assigning x
a default value if you're not confident, or if the actual logic is exceedingly obtuse.
这篇关于绊倒在C ++中的非凡布尔场景中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!