尝试静态代码分析器很容易。 但要实现它,尤其是在大型旧项目的开发中,需要技巧。 如果做得不正确,分析人员可能会增加工作量、减慢开发速度并降低团队的积极性。 让我们简单谈谈如何正确地将静态分析集成到开发过程中,并开始将其用作 CI/CD 的一部分。
介绍
最近我的注意力被《
我们的 PVS-Studio 团队就此主题发表了自己的看法。 让我们看看实现静态代码分析器的问题最初是如何出现的,如何克服这个问题,以及如何轻松地逐步消除技术债务。
问题
启动并查看静态分析器如何工作通常并不困难[
所有静态分析仪都会产生误报。 这是静态代码分析方法的一个特点,对此我们无能为力。 在一般情况下,这是一个无法解决的问题,正如赖斯定理所证实的那样[
如果静态分析器已配置,则误报不是问题:
- 禁用不相关的规则集;
- 一些不相关的诊断已被禁用;
- 如果我们谈论的是 C 或 C++,那么宏会被标记为包含特定的结构,这些结构会导致在使用此类宏的每个地方出现无用的警告;
- 自己的函数被标记为执行类似于系统函数的操作(它自己的模拟 Memcpy или 的printf)[
4 ]; - 使用注释专门禁用误报;
- 等。
在这种情况下,我们预计误报率较低,约为 10-15% [
事实上,在一个大型项目中,最初的画面会完全不同。 分析器针对遗留代码发出数百或数千条警告。 不可能快速了解这些警告中哪些是相关的,哪些是不相关的。 坐下来开始处理所有这些警告是不合理的,因为这种情况下的主要工作将停止数天或数周。 通常,团队无法承受这种情况。 还会有大量的差异破坏变更历史。 快速批量编辑代码中如此多的片段将不可避免地导致新的拼写错误和错误。
最重要的是,这种对抗警告的壮举毫无意义。 同意该项目已成功运行多年,其中大部分关键错误已得到纠正。 是的,这些修复非常昂贵,必须进行调试,收到有关错误的负面用户反馈,等等。 静态分析器将有助于在编码阶段快速且廉价地修复许多此类错误。 但目前,无论怎样,这些错误已经被修复,分析器主要检测旧代码中的非关键错误。 该代码可能不会被使用,也可能很少使用,并且其中的错误可能不会导致明显的后果。 也许按钮的阴影在某个地方颜色错误,但这不会影响任何人使用该产品。
当然,再小的错误也仍然是错误。 有时,错误可能隐藏真正的漏洞。 然而,放弃一切并花费数天/数周的时间来处理几乎不显现出来的缺陷似乎是一个可疑的想法。
程序员看着、看着、看着所有这些关于旧工作代码的警告……他们认为:我们可以不用静态分析。 让我们去写一些新的有用的功能。
以他们自己的方式,他们是对的。 他们认为首先必须以某种方式消除所有这些警告。 只有这样,他们才能从定期使用代码分析器中受益。 否则,新的警告就会被旧的警告淹没,而没有人会注意到它们。
这与编译器警告的类比相同。 他们建议将编译器警告的数量保持在 0 并不是没有道理的。如果有 1000 个警告,那么当有 1001 个时,就没有人会注意了,而且也不清楚去哪里寻找这个最新的警告。
这个故事中最糟糕的事情是,如果此时上面有人强迫您使用静态代码分析。 这只会削弱团队的积极性,因为从他们的角度来看,额外的官僚复杂性只会造成阻碍。 没有人会看分析仪的报告,所有的使用都只是“纸上谈兵”。 那些。 形式上,分析被内置到 DevOps 流程中,但实际上这对任何人都没有好处。 我们在展位上听到了与会者的详细故事。 这样的经历可能会阻碍程序员在很长一段时间内(甚至永远)使用静态分析工具。
实施和消除技术债务
事实上,即使在大型旧项目中引入静态分析也没有什么困难或可怕的。
CI / CD
此外,分析仪可以立即成为持续开发过程的一部分。 例如,PVS-Studio 发行版包含用于方便地以您需要的格式查看报告的实用程序,以及向编写有问题的代码部分的开发人员发出的通知。 对于那些对从 CI/CD 系统启动 PVS-Studio 更感兴趣的人,我建议您熟悉相应的内容
PVS-Studio 走向云端:Azure Devops PVS-Studio 走向云端:Travis CI PVS-Studio 走向云端:GitLab CI/CD PVS-Studio 走向云端:CircleCI
但让我们回到在实施代码分析工具的第一阶段出现大量误报的问题。
修复现有技术债务并处理新警告
现代商业静态分析器允许您仅研究新代码或更改代码中出现的新警告。 这种机制的实现方式各有不同,但本质是一样的。 在PVS-Studio静态分析仪中,该功能的实现如下。
为了快速开始使用静态分析,我们建议PVS-Studio用户使用批量抑制警告的机制[
您可以告诉 PVS-Studio 认为这些警告暂时无关紧要(为以后保留技术债务),并且它将不再显示它们。 分析器创建一个特殊文件,其中保存有关尚不感兴趣的错误的信息。 现在,PVS-Studio 将仅针对新的或更改的代码发出警告。 而且,这一切都是巧妙实施的。 例如,如果在源代码文件的开头添加一个空行,那么分析器就会明白,实际上什么都没有改变,并且将继续保持沉默。 该标记文件可以放入版本控制系统中。 文件很大,但这不是问题,因为经常存储它没有意义。
现在,所有程序员都会看到仅与新代码或更改代码相关的警告。 因此,正如他们所说,您可以从第二天开始使用分析仪。 您可以稍后返回技术债务,并逐步纠正错误并配置分析器。
这样,在大型旧项目中实施分析器的第一个问题就已经解决了。 现在让我们弄清楚如何处理技术债务。
错误修复和重构
最简单、最自然的事情就是留出一些时间来分析大量被抑制的分析器警告并逐步处理它们。 在某个地方你应该修复代码中的错误,在某个地方你应该重构以告诉分析器代码没有问题。 简单的例子:
if (a = b)
大多数 C++ 编译器和分析器都会抱怨此类代码,因为他们实际上想要编写的可能性很高 (a==b)。 但有一个不言而喻的约定,并且这通常会在文档中注明,即如果有额外的括号,那么就认为程序员故意编写了这样的代码,无需发誓。 例如,在 PVS-Studio 诊断文档中
if ((a = b))
另一个例子。 这段C++代码中是否忘记了? 打破 或不?
case A:
foo();
case B:
bar();
break;
PVS-Studio 分析仪将在此处发出警告
case A:
foo();
[[fallthrough]];
case B:
bar();
break;
可以说这样的代码修改并没有修复bug。 是的,这是事实,但它做了两件有用的事情。 首先,分析仪报告消除了误报。 其次,代码对于参与维护的人员来说变得更容易理解。 这非常重要! 仅此一点,就值得进行一些小的重构,以使代码更清晰、更易于维护。 由于分析器不知道是否需要“break”,因此其他程序员也不清楚。
除了错误修复和重构之外,您还可以专门抑制明显错误的分析器警告。 可以禁用一些不相关的诊断。 例如,有人认为警告毫无意义
还有其他方法可以抑制误报。 例如前面提到的宏标记。 所有这些在文档中都有更详细的描述。 最重要的是要明白,如果你逐步、系统地处理误报,那么它们并没有什么问题。 绝大多数无趣的警告在配置后就消失了,只剩下真正需要仔细研究的地方和代码中的一些更改。
此外,如果出现任何困难,我们总是帮助客户建立PVS-Studio。 此外,在某些情况下,我们自己消除了错误警告并纠正了错误[
棘轮法
还有另一种有趣的方法可以通过消除静态分析器警告来逐步提高代码质量。 最重要的是,警告的数量只会减少。
记录静态分析仪发出的警告次数。 质量门的配置方式是现在您只能输入不会增加操作次数的代码。 因此,逐渐减少警报数量的过程是从调整分析仪和纠正错误开始的。
即使一个人想作一点小作弊,并决定通过改进旧的第三方代码而不是消除新代码中的警告来通过质量关卡,这并不可怕。 尽管如此,棘轮朝一个方向旋转,缺陷的数量会逐渐减少。 即使一个人不想修复自己的新缺陷,他仍然需要改进相邻代码中的某些内容。 在某些时候,减少警告数量的简单方法就会结束,而真正的错误将会得到修复。
Ivan Ponomarev 在一篇非常有趣的文章中更详细地描述了这种方法“
文章作者也有关于这个话题的报告:“
结论
我希望读完这篇文章后,读者能够更加接受静态分析工具,并愿意将它们应用到开发过程中。 如果您有任何疑问,我们随时准备着
对于静态分析是否真的方便和有用还有其他典型的疑问。 我在《开发过程中引入PVS-Studio静态代码分析器的原因》一书中试图消除大部分疑虑[
感谢您的关注并前来
附加链接
- 安德烈·卡尔波夫。
如何快速查看 PVS-Studio 分析器为 C 和 C++ 代码生成的有趣警告? - 维基百科。
赖斯定理 . - 安德烈·卡尔波夫,维多利亚·哈涅娃。
使用机器学习进行程序源代码静态分析 . - PVS-工作室。 文档。
附加诊断设置 . - 安德烈·卡尔波夫。
使用 EFL Core Libraries 示例的 PVS-Studio 分析器的特征,误报率为 10-15% . - PVS-工作室。 文档。
分析仪消息的批量抑制 . - 伊万·安德里亚辛。
关于我们如何测试 X 射线血管内手术教育模拟器项目的静态分析 . - 帕维尔·叶列梅耶夫,斯维亚托斯拉夫·拉兹梅斯洛夫。
PVS-Studio 团队如何改进虚幻引擎代码 . - 安德烈·卡尔波夫。
在开发过程中引入静态代码分析器PVS-Studio的原因 .
如果您想与英语读者分享这篇文章,请使用翻译链接:Andrey Karpov。
来源: habr.com