C++静态代码分析工具是否值得使用?

30
我们的管理层最近与一些销售C++ 静态分析工具的人进行了交流。当然,销售人员会说他们能找到大量的漏洞,但我持怀疑态度。
这类工具在实际应用中如何工作?它们真的能找到实际存在的漏洞吗?它们是否有助于初级程序员学习?
值得花费精力去使用它们吗?

4
约翰·卡马克最近写了一篇文章,讨论了静态代码分析。文章链接为:http://altdevblogaday.com/2011/12/24/static-code-analysis/。 - Richard Corden
John Carmack。静态代码分析。新链接:http://www.viva64.com/en/a/0087/ - user965097
@DavidNorman:它们都只进行逐个文件的分析,因此如果您想分析函数在源文件之间的交互方式,您仍然需要雇用多个人(因为这些工具无法执行整个程序分析)。 - user2284570
14个回答

28

静态代码分析几乎总是值得做的。对于现有的代码库而言,问题在于它可能会报告太多的错误,使其开箱即用不太实用。

我曾经参与过一个项目,在编译器中有100,000多个警告...在那种代码库上运行Lint工具毫无意义。

正确使用Lint工具意味着购买更好的流程(这是一件好事)。我最好的工作之一是在一个研究实验室工作,我们不允许提交带有警告的代码。

所以,是的,工具是值得的...从长远来看。短期内,将编译器警告调到最高级别,看看它会报告什么。如果代码是“干净”的,那么现在就是查看Lint工具的时候了。如果代码有很多警告...优先处理并修复它们。一旦代码没有(或至少非常少)警告,那么再考虑使用Lint工具。

因此,Lint工具不能帮助解决糟糕的代码库问题,但一旦你拥有了良好的代码库,它可以帮助你保持代码库的良好状态。

编辑:

在这个存在100,000多个警告的项目中,它被分解成大约60个Visual Studio项目。每当一个项目删除了所有警告后,就会将其更改为警告是错误,并防止在已清理的项目中添加新警告(或者让我的同事在开发人员提交代码之前就有权利大声吼叫 :-))。


2
最近我在公司为一个新的硬件/软件产品工作,我很幸运地说服了负责人将一些编译器警告改成错误。这个从警告到错误的变化迫使每个人都要摆脱这些警告。 - Trevor Boyd Smith
这个编译器标志的更改是我最好的选择,它可以在不实际发送电子邮件命令给每个人的情况下改变我们的“编码风格”和“流程”。 - Trevor Boyd Smith
我认为我最开心的一天之一是将/W4更改提交到60个项目中去 :-) - TofuBeer
实际上有一个/Wall选项可以启用所有警告。/W4默认情况下仍然有一些被禁用。http://msdn.microsoft.com/en-us/library/thxezb7y.aspx - FkYkko
我认为,在产品达到发布里程碑时,处理这些 10 万个警告的最佳方法就是忽略它们——太多了,难以应对。但是,任何会产生警告的新代码都不应该进入代码库,并且这一点应该得到强制执行。除了 Lint 之外,PVS-Studio(http://pvs-studio.viva64.com)有一种非常简单的方法可以一次性“忽略”所有警告。 - Alex Z
显示剩余2条评论

10
在我与几个雇主的经验中,Coverity Prevent for C/C++绝对是值得的,即使在优秀开发人员的代码中也能找到一些错误,并且在最差的开发人员的代码中找到很多错误。其他人已经介绍了技术方面,所以我将重点关注政治难题。
首先,最需要静态分析的开发人员最不可能自愿使用它。因此,我担心实践和理论上都需要强有力的管理支持;否则,它可能只会成为一个检查清单项目,用于生成令人印象深刻的指标,而没有真正修复错误。任何静态分析工具都会产生误报;你可能需要将某人专门用于最小化这些麻烦,例如通过分类缺陷、优先考虑检查器和调整设置。(商业工具应极大地避免再次显示假阳性;这本身可能就足以赢得价格。)即使是真正的缺陷也可能会产生烦恼;我的建议是不要担心例如检入评论抱怨明显具有破坏性的错误“较小”的问题。
我最大的建议是第一定律的一个推论:先打便宜球,从最差开发人员的显然错误开始。其中一些甚至可能已经被编译器警告找到了,但很多错误可能会从这些裂缝中滑过去,例如当它们被命令行选项抑制时。非常明显的错误在政治上可能很有用,例如最有趣的缺陷十大列表,如果谨慎使用,可以集中思想。

Coverity只能进行逐个文件的分析,因此如果您想分析函数在源文件之间的交互方式,仍需要雇用多人(因为这些工具无法执行整个程序的分析)。 - user2284570

6
正如一些人所说,如果你在大多数应用程序上全力运行静态分析工具,你会得到很多警告,其中一些可能是误报或不会导致可利用的缺陷。这种经验导致了这些类型的工具嘈杂且可能浪费时间的看法。然而,有些警告将突出显示真实且潜在危险的缺陷,这些缺陷可能会导致安全、可靠性或正确性问题,对于许多团队来说,这些问题很重要,并且几乎不可能通过测试发现。
也就是说,静态分析工具可以极大地帮助,但将它们应用于现有的代码库需要一些策略。以下是几个可能有助于您的提示:
1)不要一次性打开所有功能,选择一个初始的缺陷集,打开这些分析并在整个代码库中修复它们。
2)当您正在解决某类缺陷时,请帮助整个开发团队了解该缺陷的原因以及如何编写代码来防御该缺陷。
3)努力完全清除该类缺陷的代码库。
4)一旦解决了这类问题,请引入一种机制以保持零问题状态。幸运的是,如果您处于没有错误的基线状态,确保不会重新引入错误要容易得多。

5

这确实有帮助。我建议您试用一下,并将其运行到您认为被忽视的代码库的一部分中。这些工具会产生很多误报。一旦您处理完这些,您可能会发现一个或两个缓冲区溢出错误,这可以在不久的将来避免很多麻烦。此外,请至少尝试两三种不同的工具(也包括一些开源工具)。


+1 建议使用试用版本。我本来就打算这么做的。 - David Thornley

4
我曾经使用过一些工具,例如PC-Lint,它们确实发现了一些问题。通常它们是可配置的,你可以告诉它们“不要再打扰我关于xyz的事情”,如果你确定xyz真的不是一个问题。
我不知道它们是否能帮助初级程序员学到更多,但它们可以被用作帮助优化代码的机制。
我发现第二组(怀疑的,寻找漏洞的)眼睛和单元测试通常是我看到更多缺陷捕获的地方。

6
当我在一个 C++ 项目中使用 PC-Lint 时,我打开了 Effective C++ / More Effective C++ 警告,并在违反规则时重新阅读了书中的相关章节。这真的帮助我更好地理解这些规则在实际情况下的应用。我觉得这非常有益。 - Trent

4

这些工具确实有帮助。对于C开发人员来说,lint一直是一个很好的工具。

但我有一个反对意见,它们都是批处理进程,需要在你写完大量代码后运行,可能会生成很多消息。

我认为更好的方法是将其构建到你的IDE中,并在你编写代码时指出问题,以便你可以立即进行更正。不要让这些问题首先进入代码库。

这就是Java的FindBugs静态分析工具和IntelliJ的Inspector之间的区别。我非常喜欢后者。


有一个适用于FindBugs的Eclipse插件。 - Mike Daniels
你有C++交互式静态分析工具的例子吗?我从未见过,但我很想看看。 - Tom
我在redlizards.com是一名开发人员 - 我们制作了Goanna,这是一个C / C ++静态分析工具,有不同的版本可供夜间构建运行,也可以集成到IDE中(VS和eclipse插件)。值得一看。 - Dominic Gurto

4
如果你的代码基础很大,那么你可能需要处理大量的误报。大多数静态分析工具使用“单过程分析”来工作,这意味着它们将每个过程视为独立的,而不是使用“整个程序分析”来考虑整个程序。它们通常使用“单过程分析”,因为“整个程序分析”必须考虑程序中实际上永远不会发生的许多路径,并且因此通常会产生错误的阳性结果。单过程分析通过仅关注单个过程消除了这些问题。然而,为了使其工作,它们通常需要引入一种“注释语言”,您可以使用该语言描述过程参数、返回类型和对象字段的元数据。对于C++,这些通常是通过装饰物实现的。然后,注释会描述诸如“此字段永远不为空”、“此字符串缓冲区由此整数值保护”、“仅可由标记为‘background’的线程访问此字段”等内容。然后,分析工具将采取您提供的注释并验证您编写的代码是否符合注释。例如,如果您可能将一个标记为非空的值传递给某个函数,那么它将标记错误。在没有注释的情况下,该工具需要假设最坏的情况,因此会报告很多不是真正错误的错误。由于您似乎还没有使用这样的工具,所以应该假设您将需要花费相当长的时间来注释代码,以摆脱最初报告的所有误报。我建议您首先运行该工具,并计算出错误数。这应该可以给您一个采用该工具的代码库所需的时间估计。该工具是否值得取决于您的组织。您最常遇到哪些类型的错误?它们是缓冲区溢出错误吗?它们是空指针引用或内存泄漏错误吗?它们是线程问题吗?它们是“糟糕,我们没有考虑到那种情况”,还是“我们没有测试在Windows 98的Lithuanian版本上运行的中文版本产品”?确定问题后,您就应该知道是否值得投入精力。该工具可能会有助于缓冲区溢出、空指针引用和内存泄漏错误。如果支持“线程着色”、“效果”或“权限”分析,则可能有助于处理线程问题。然而,这些类型的分析非常尖端,并且有巨大的符号负担,因此它们确实带来了一些代价。该工具可能不会帮助处理任何其他类型的错误。因此,它确实取决于您编写的软件类型以及您最常遇到的错误类型。

C++的一个好处是,内联函数和模板意味着大量信息可以在单个TU中使用。因此,一个好的静态分析工具可以对TU中可见的函数执行跨过程分析。 - Richard Corden
我的主要观点是这些工具可能有很高的采用成本,而且只能捕捉到一定类别的错误。这意味着它们不是“通用”的解决方案。它们对于某些项目可能至关重要,但对于其他项目可能是浪费时间。使用它们应该基于个人需求。 - Scott Wisniewski

3
我认为静态代码分析是非常值得的,但前提是你使用的是正确的工具。最近,我们尝试了Coverity工具(有些昂贵),这个工具真的很棒,它找出了很多关键缺陷,这些缺陷在lint或purify中都没有检测到。
此外,我们发现如果早些时候使用Coverity,我们可以避免35%的客户现场问题。
现在,我们公司已经推广使用Coverity了,每当我们收到一个旧软件版本的客户TR时,我们都会对其运行Coverity以找出可能存在的故障候选项,然后在子系统中开始分析。

2
付费使用大多数静态分析工具可能是不必要的,因为有一些非常高质量的免费工具(除非你需要商业版提供的某些非常特殊或特定的功能)。例如,查看我在另一个关于cppcheck的问题上所给出的答案。请参考cppcheck

2

我猜这取决于你的编程风格。如果你主要编写C代码(偶尔使用C++功能),那么这些工具可能会有所帮助(例如内存管理,缓冲区溢出等)。但是,如果你正在使用更复杂的C++功能,则当尝试解析源代码时,这些工具可能会感到困惑(或者仅仅因为C++设施通常更安全而无法找到许多问题)。


这与我的经验相符。3或4年前我使用PC-Lint时,它太吵了,即使调整了参数,它仍然会抱怨很多不是问题的东西。 - Brian Neal
这是在一个使用相当先进的C++特性的代码库中。 - Brian Neal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接