在c++中偶然发现了一个重要的bool场景
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;
// 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个参数。
在Cppcheck中为假阳性。I 通过添加内联抑制来解决问题:[1]
if ( !pre ) {
trace("pre failed");
// cppcheck-suppress uninitvar
} else if ( !x ) {
trace("x failed");
} else {
trace("post failed");
}
,我也提请Cppcheck开发人员注意:
#7663(误报:不可达代码中未初始化的变量)
[1]我决定不初始化变量。这不是出于性能原因,而是为了在将来的版本中获知该错误正在修复,届时Cppcheck将显示
Id: unmatchedSuppression
Summary: Unmatched suppression: uninitvar
Message: Unmatched suppression: uninitvar
静态分析似乎在抱怨,因为如果pre
为假,那么x
永远不会设置。
你的代码结构使得x
的值永远不会被访问,如果pre
为 false -我认为静态分析器在这种情况下没有给出有用的输出。
列举我们拥有的各种情况(因此我们可以合理地确定它是cppcheck而不是我们!):
-
第一个访问
x
的语句在if ( !pre || !x || !post )
行-由于短路求值:如果A
为真,if( A || B || C )
不求B
或C
;因此,我们从不尝试读取未初始化的x
(因为x
只有在pre
为false时才未初始化,在这种情况下,我们停止对表达式求值!) -
第二个用法在
if ( !pre ) { trace("pre failed"); } else if ( !x ) { // <-- HERE Cppcheck complains
同样,只有当
pre
为true时(在这种情况下,x
被正确初始化),我们才能击中违规行。
由此,我们可以得出结论:
-
实际代码在某些情况下错误地试图读取
x
,即使pre
是假的,并且在构建示例时您已经错过了它(有时程序的逻辑流可能有点迟钝) -
静态分析器是惰性的,它发现
else if( !x )
行,并且不能确定该行是否具有未初始化的值。
从你提供的代码来看,你不应该担心:静态分析工具在技术上是正确的,x
可以被未初始化,但在那些情况下,它不被使用(因此可能不应该警告你)。
我建议给x
分配一个默认值,如果你不自信,或者如果实际的逻辑是非常迟钝的。
如果您的pre
条件为false
,则x将未初始化。在if ( !x )
行,CppCheck警告使用不确定的值。要修复它,请初始化x
变量
- 运行同一解决方案的另一个项目的项目
- 在c++中用vector填充一个简单的动态数组
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 如何返回一个类的两个对象相加的结果
- 使用std::transform将一个范围的元素添加到另一个范围中
- 如何创建一个空的全局类并在启动时实例化它
- 如何获取一个数字的前3位
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- 获取向量C++中第一个值和最后一个值的和
- C++-我可以创建另一个类的成员并在构造函数中使用它吗
- c++多进程编写一个唯一的文件
- 如何使用CLion在Mac上创建一个新的.txt文件
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 如何将一个类的函数作为另一个类的另一个函数的参数传递
- 检查哪个对象调用了另一个对象的对象方法
- 修改的Fibbonaci C++得到一个大的负数
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- 在c++中偶然发现了一个重要的bool场景