Visual Studio 2022:新的枚举检查规则

Visual Studio 2022:新的枚举检查规则

作者:BlogUpdater |  时间:2022-04-14 |  浏览:207 |  评论已关闭 条评论

实际上,我们内部有一个C++静态分析团队,他们的主要目标是:让C++开发者尽可能地编写安全的代码。静态分析团队努力工作,持续地添加代码安全检查规则,并积极解决C++开发社区提交的各类高优先级问题。感谢各位开发者一直以来给我们提供的使用反馈和建议。今天的文章的内容,主要是概述了一些关于枚举使用相关的代码检查规则,这些规则会指出枚举的误用场景,并对现有的枚举检查做出了一些改进。

概述
我们引入了三项检查来找出枚举位操作方面的误用。这些检查源于真实产品代码中的发现的Bug。我们同时也通过建议使用C11的enum(而不是之前的遗留版本)来对改进检查规则。如果你想了解更多信息,请参考关于”如何在工程上启用代码检查”的文档。

按位枚举(Bitwise enumerations)
有一些枚举会将它的枚举值定义为2的次方。通常这种定义的使用场景是用来实现一个位操作,这样就可以方便进行位合并和检查。新的代码检查规则将会尝试检测对于这种枚举的误用。
但是,需要注意了,因为没有一个明确的规则能判定一个枚举是否可以看做一个位枚举,所以,我们的检查依赖于一组启发式方法从源代码中推断出意图。
下面,我们来看一个只有两个元素的枚举:

因为我们不能确定枚举E的值是否是想形成2的次方 (1,2,4,8,…),或者只是简单地增加 1 (1,2,3 ,4,…)。 如果没有额外的上下文,我们无法判断E是否是按位枚举来用于按位运算,或者它是否只是一个常规枚举。

我们再来看下面这个枚举:

在上面的枚举中,最后一个枚举常量不是 2 的次方。 在所有相关位都设置的情况下定义一个常量是一种常见的习惯用法。 对于某些正 k,这些常数通常具有 2^k-1 的值。 我们的检查会将这种形状的枚举视为按位计算。 我们必须小心这两种启发式的相互作用。

再来看下面两个枚举:

在上面的例子中,我们不想将E1视作按位枚举,尽管它的最后一个元素的值为 2^2-1。 另一方面,我们绝对希望将 E2 视为按位枚举。

这些启发式方法对于我们测试检查的项目相当有效。 如果你遇到任何误报或误报,请告诉我们。

C26813
规则 C26813 将找到使用 operator== 测试按位枚举值的代码模式。 在大多数情况下,保存按位枚举值的变量代表一个位域。 要查询是否在此变量中设置了特定的枚举器值,应使用按位运算。 不这样做会产生不正确的结果,如下图所示:

在对一些真实世界的代码运行此检查后,我们还遇到了枚举具有两个值的幂但从未与按位运算一起使用的情况。 在这些情况下,更改枚举常量的值以使代码中的意图更清晰可能是个好主意。

C26827
规则 C26827 可以帮助检测我们忘记添加初始化程序的按位枚举中的枚举数常量。 考虑以下示例:

在这里,我们在按位运算中使用枚举常量,但并非所有常量都具有 2^k 或 2^k-1 的形式。 事实上,它的一个常数 D 具有 2^k+1 的形式。 当我们添加一个新常量而不定义它的值时,就会发生这种模式。

但是,这个检查存在限制。 它仅适用于范围枚举,因为编译器会在静态分析阶段之前将常规枚举转换为整数。 我们正在寻找改进代码内部表示的方法,以便对代码的编写方式有更高的准确度,这将在未来实现更好的诊断。

C26828
规则 C26828 将标记来自不同枚举的值混合的按位表达式。 考虑以下示例:

这里 BitWiseA 和 BitWiseB 具有重叠值。 我们不太可能希望在同一个按位表达式中同时使用两者。 这可能是拼写错误的结果。

此检查具有与 C26827 类似的限制。

对 C26812 的改进
规则 C26812 建议,在旧版枚举上使用新的 C++11 范围枚举。 长期以来,此检查一直是我们产品的一部分,但仍有改进的余地。 以前,它在其使用站点而不是在其声明处诊断遗留枚举。 这有几个问题:
> 我们没有对未使用的枚举发出警告。
> 不可能在声明中禁止所有出现此警告的情况,开发者社区也报告了这个问题。
> 它不适用于新的 /external 功能。
> 错误诊断的位置可能远离其声明位置,这使得解决警告变得更加困难。

此检查的新版本将对声明而不是使用发出诊断。 在大多数情况下,这应该会改善用户体验。 我们还意识到,解决此错误有时代价高昂或根本不可能(例如,库可能需要向后兼容)。 为了解决这个问题,我们从 NativeRecommendedRules 规则集中删除了这条规则,并创建了一个名为 CppCoreCheckEnumRules 的新规则集,以包含我们在这篇文章中提到的所有 4 条规则。

总结
即将推出的 Visual Studio 2022 17.2 Preview 3 将提供新的检查功能,以发现难以发现的枚举误用问题。 它还将包括对现有检查的一些质量改进,可以帮助将代码库迁移到范围枚举。 三个新的与枚举相关的检查是 NativeRecommendedRules 规则集的一部分,并且更新的警告已移至 CppCoreCheckEnumRules。

最后
Microsoft Visual C++团队的博客是我非常喜欢的博客之一,里面有很多关于Visual C++的知识和最新开发进展。大浪淘沙,如果你对Visual C++这门古老的技术还是那么感兴趣,则可以经常去他们那(或者我这)逛逛。
本文来自:《New Enumeration Checks in Visual Studio 2022 version 17.2 Preview 3》

最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

标签:

评论已关闭。