31

我们的管理层最近一直在与一些销售 C++静态分析工具的人交谈。当然,销售人员说他们会发现很多错误,但我对此表示怀疑。

这些工具在现实世界中如何工作?他们能找到真正的错误吗?它们是否帮助更多初级程序员学习?

他们值得麻烦吗?

4

14 回答 14

29

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

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

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

所以,是的,这些工具是值得的……从长远来看。在短期内将你的编译器警告调到最大,看看它报告了什么。如果代码是“干净的”,那么现在是时候查看 lint 工具了。如果代码有很多警告...优先考虑并修复它们。一旦代码没有(或至少很少)警告,然后查看 Lint 工具。

所以,Lint 工具不会帮助糟糕的代码库,但是一旦你拥有了一个好的代码库,它就可以帮助你保持良好的状态。

编辑:

以 100,000+ 个警告产品为例,它被分解为大约 60 个 Visual Studio 项目。由于每个项目都删除了所有警告,因此它已更改为警告是错误,这会阻止将新警告添加到已清理的项目中(或者更确切地说,它让我的同事对任何签入的开发人员大吼大叫无需先编译的代码:-)

于 2009-03-12T18:19:03.747 回答
10

根据我与几个雇主的经验,C/C++ 的 Coverity Prevent 绝对是值得的,即使在优秀的开发人员的代码中也能发现一些错误,而在最差的开发人员的代码中也会发现很多错误。其他人已经涵盖了技术方面,所以我将专注于政治困难。

首先,代码最需要静态分析的开发人员,最不可能主动使用它。所以恐怕你需要强大的管理支持,无论是在实践中还是在理论上;否则它可能最终只是一个清单项目,产生令人印象深刻的指标而实际上没有修复错误。任何静态分析工具都会产生误报;您可能需要派人来尽量减少他们的烦恼,例如,通过对缺陷进行分类、确定检查程序的优先级以及调整设置。(商业工具应该非常擅长从不多次显示误报;仅此一项可能就值得付出代价。)即使是真正的缺陷也可能会产生烦恼;我对此的建议是不要担心,例如,签入评论抱怨明显具有破坏性的错误是“次要的。

我最大的一条建议是我的第一定律的推论,上面:首先采取廉价的措施,然后看看你最糟糕的开发人员的痛苦明显的错误。其中一些甚至可能已经被编译器警告发现,但是很多错误可能会从这些裂缝中溜走,例如,当它们被命令行选项抑制时。真正明显的错误可能在政治上很有用,例如,最有趣的十大缺陷列表,如果小心使用,可以很好地集中注意力。

于 2009-03-30T19:29:20.320 回答
6

正如一些人所说,如果您在大多数应用程序上全速运行静态分析工具,您会收到很多警告,其中一些可能是误报,或者可能不会导致可利用的缺陷。正是这种经验导致人们认为这些类型的工具很吵,而且可能是在浪费时间。但是,有些警告会突出显示可能导致安全性、可靠性或正确性问题的真实且潜在危险的缺陷,并且对于许多团队而言,这些问题对于修复很重要,并且可能几乎不可能通过测试发现。

也就是说,静态分析工具非常有用,但将它们应用到现有代码库需要一点策略。这里有一些提示可能对您有所帮助。

1)不要一次打开所有东西,决定一组初始缺陷,打开这些分析并在你的代码库中修复它们。

2) 当您解决一类缺陷时,帮助您的整个开发团队了解缺陷是什么、为什么它很重要以及如何编写代码来防御该缺陷。

3) 努力彻底清除代码库中的此类缺陷。

4)一旦此类问题得到解决,引入一种机制以保持零问题状态。幸运的是,如果您处于基线没有错误,确保您没有重新引入错误要容易得多。

于 2009-05-31T11:11:49.720 回答
5

它确实有帮助。我建议您使用试用版并通过您认为被忽略的代码库的一部分运行它。这些工具会产生很多误报。一旦你涉水过这些,你可能会发现一个或两个缓冲区溢出,可以在不久的将来节省很多悲伤。此外,尝试至少两个/三个品种(以及一些开源的东西)。

于 2009-03-12T17:45:20.863 回答
4

您可能必须处理大量误报,尤其是在您的代码库很大的情况下。

大多数静态分析工具使用“过程内分析”工作,这意味着它们单独考虑每个过程,而不是考虑整个程序的“整个程序分析”。

他们通常使用“程序内”分析,因为“整个程序分析”必须考虑通过程序的许多路径,这些路径实际上不会在实践中发生,因此通常会产生误报结果。

程序内分析通过只关注单个程序来消除这些问题。然而,为了工作,它们通常需要引入一种“注释语言”,用于描述过程参数、返回类型和对象字段的元数据。对于 C++,这些东西通常是通过你用来装饰东西的宏来实现的。然后注释描述了诸如“这个字段永远不会为空”、“这个字符串缓冲区由这个整数值保护”、“这个字段只能被标记为'background'的线程访问”等内容。

然后,分析工具将获取您提供的注释并验证您编写的代码实际上是否符合注释。例如,如果您可能将 null 传递给标记为非 null 的内容,它将标记错误。

在没有注释的情况下,该工具需要假设最坏的情况,因此会报告很多并非真正错误的错误。

由于您似乎还没有使用这样的工具,因此您应该假设您将不得不花费大量时间注释您的代码以消除最初报告的所有误报。我最初会运行该工具,并计算错误的数量。这应该让您估计在您的代码库中采用它需要多长时间。

该工具是否值得取决于您的组织。你最常咬的虫子有哪些?它们是缓冲区溢出错误吗?它们是空解引用还是内存泄漏错误?他们是线程问题吗?他们是“哎呀,我们没有考虑这种情况”,还是“我们没有测试在立陶宛版本的 Windows 98 上运行的我们产品的中文版本?”。

一旦你弄清楚问题是什么,那么你应该知道它是否值得付出努力。

该工具可能有助于解决缓冲区溢出、null 取消引用和内存泄漏错误。如果它支持“线程着色”、“效果”或“权限”分析,它可能有助于解决线程错误。然而,这些类型的分析是非常先进的,并且有巨大的符号负担,所以它们确实需要一些费用。该工具可能无法解决任何其他类型的错误。

因此,这实际上取决于您编写的软件类型以及您最常遇到的错误类型。

于 2009-03-12T18:36:58.383 回答
4

我用过它们——例如 PC-Lint,它们确实找到了一些东西。通常它们是可配置的,如果您确定 xyz 确实不是问题,您可以告诉他们“不要再为 xyz 打扰我”。

我不知道它们帮助初级程序员学到了很多东西,但它们可以作为一种机制来帮助收紧代码。

我发现第二组(怀疑的,探索错误的)眼睛和单元测试通常是我看到更多错误捕获发生的地方。

于 2009-03-12T17:43:38.213 回答
4

这些工具确实有帮助。lint 一直是 C 开发人员的绝佳工具。

但我的一个反对意见是,它们是在您编写了大量代码并可能生成大量消息之后运行的批处理过程。

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

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

于 2009-03-12T17:55:22.960 回答
3

如果您使用正确的工具,我认为静态代码分析非常值得。最近,我们尝试了 Coverity Tool(有点贵)。它太棒了,它带来了许多严重的缺陷,这些缺陷是 lint 或 purify 无法检测到的。

我们还发现,如果我们早先使用覆盖率,我们可以避免 35% 的客户现场缺陷。

现在,Coverity 在我的公司推出,当我们在旧软件版本中获得客户 TR 时,我们会针对它运行 Coverity,以便在我们开始对 susbsytem 进行分析之前找出可能的故障候选者。

于 2009-03-13T10:00:13.047 回答
2

与所有事情一样,答案取决于......如果您是为您的祖母开发针织图案漂亮打印机的唯一开发人员,您可能不想购买任何静态分析工具。如果您有一个中等规模的软件项目,该项目将涉及一些重要的事情,而且您的日程安排可能很紧,那么您现在可能想要投资一点,以便以后节省更多。

我最近写了一篇关于此的一般咆哮:http ://www.redlizards.com/blog/?p=29

我应该在时间允许的情况下尽快写第二部分,但总的来说,粗略计算一下是否值得:

  • 调试花了多少时间?
  • 绑定了多少资源?
  • 通过静态分析可以找到多少百分比?
  • 工具设置成本?
  • 购买价格?
  • 内心的平静?:-)

我个人的看法也是:

  • 尽早进行静态分析

    • 项目初期
    • 在开发周期的早期
    • 早在很早的时候(在夜间构建和后续测试之前)
  • 为开发者提供自己使用静态分析的能力

    • 没有人喜欢被测试工程师或一些匿名工具告诉他们昨天做错了什么
    • 更少的调试让开发人员高兴:-)
    • 提供了一种很好的方式来了解(微妙的)陷阱而不会尴尬
于 2009-05-19T03:37:50.600 回答
2

我想这在很大程度上取决于您的编程风格。如果您主要编写 C 代码(偶尔使用 C++ 功能),那么这些工具可能会有所帮助(例如内存管理、缓冲区溢出……)。但是,如果您使用的是更复杂的 C++ 功能,那么在尝试解析源代码时这些工具可能会感到困惑(或者只是找不到很多问题,因为 C++ 工具通常使用起来更安全)。

于 2009-03-12T18:16:31.380 回答
2

这个相当惊人的结果是使用 Elsa 和 Oink 完成的。

http://www.cs.berkeley.edu/~daw/papers/fmtstr-plas07.pdf

“Debian Linux 中格式字符串漏洞的大规模分析”,作者:Karl Chen、David Wagner,加州大学伯克利分校,{quarl, daw}@cs.berkeley.edu

抽象的:

格式字符串漏洞是一种比较常见的安全漏洞,可导致任意代码执行。与其他人合作,我们设计并实现了一个系统,以消除整个 Linux 发行版中的格式字符串漏洞,使用类型限定符推断,一种可以发现污染违规的静态分析技术。我们成功分析了 Debian 3.1 Linux 发行版中 66% 的 C/C++ 源代码包。我们的系统发现了 1,533 个格式字符串污染警告。我们估计其中 85% 是真阳性,即真正的错误;忽略来自库的重复项,大约 75% 是真正的错误。我们建议存在该技术以在不久的将来消除格式字符串漏洞。

类别和主题描述符 D.4.6 [操作系统]:安全和保护——侵入性软件;一般条款:安全性、语言;关键词:格式字符串漏洞,大规模分析,类型限定符推断

于 2012-01-26T07:27:13.320 回答
2

当有一些非常优质的免费工具时,可能不需要为大多数静态分析工具付费(除非您需要商业版本提供的一些非常特殊或特定的功能)。例如,请参阅我在另一个关于cppcheck的问题上给出的答案。

于 2009-03-12T17:41:46.097 回答
1

发现真正错误的静态分析是值得的,无论它是否是 C++。有些往往很吵,但如果他们能捕捉到细微的错误,比如有符号/无符号比较导致优化破坏你的代码或越界数组访问,他们绝对值得付出努力。

于 2009-03-12T18:21:26.203 回答
0

在前雇主,我们有 Insure++。它有助于查明 Valgrind 找不到的随机行为(使用未初始化的东西)。但最重要的是:它有助于消除尚未被称为错误的错误。

Insure++ 很好,但价格昂贵,这就是我们只购买一个用户许可证的原因。

于 2011-04-26T12:09:33.180 回答