PVS Studio 的作者是一名 C++ 静态分析师,他公布了对 CoreCLR 源代码的研究结果。虽然他的主要意图是演示工具,但它也揭示了写零缺陷的 C++ 代码是多么地难。
他们找到的第一个缺陷是手误的错误。看看下面这行代码:
if ((tree->gtOper == GT_CLS_VAR || tree->gtOper == GT_CLS_VAR) && i == 1)
很显然,它把一个变量与一个常量比较了两次,所以这可能是个复制 - 粘贴的错误。(这种错误可能在任何语言中都会存在。)
它们发现的另一个手误的错误应该会发生在 C 风格的语言中,那就是变量初始化它自身。
CorElementType elemType = elemType = TryEncodeUsingShortcut(pMT);
到现在为止所说的缺陷都比较容易通过代码审查找出来。下面这个就不行喽:
CodeGenInterface::CodeGenInterface(Compiler* theCompiler) : compiler(theCompiler), gcInfo(theCompiler), regSet(theCompiler, gcInfo) { }
只通过这段代码你发现不了什么,但是 regSet 要在 gcInfo 之前初始化。 Svyatoslav Razmyslov 解释说,
标准规定,在构建函数中的类成员初始化的顺序和它们在该类中的声明顺序是一样的。为了修复这个错误,我们应该移动类成员’gcInfo’声明的位置。
如果不用类似于 PVS Studio 这样的工具,那么发现这类缺陷的唯一方式就是手工比较这些成员变量声明的顺序以及它们在构造函数中需要被初始化的顺序。另外,无知的重构(比如把域按字母顺序予以排列)也会引入缺陷。
那么重点在于,C++ 编程如此之难。还有更多的例子,可阅读此篇文章: PVS-Studio: 25 Suspicious Code Fragments in CoreCLR .
评论