【问题标题】:Are C++ static code analyis tools worth it?C++ 静态代码分析工具值得吗?
【发布时间】:2010-10-12 23:40:47
【问题描述】:

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

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

他们值得麻烦吗?

【问题讨论】:

  • John Carmack 最近写了这篇文章:altdevblogaday.com/2011/12/24/static-code-analysis
  • 约翰·卡马克。静态代码分析。新链接:viva64.com/en/a/0087
  • @DavidNorman : 他们都只做逐个文件的分析,所以如果你想分析源文件之间的函数如何交互,你需要雇佣几个人(因为这些工具不是能够执行整个程序分析).

标签: c++ static-analysis


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 当我在一个 C++ 项目中使用 PC-Lint 时,我打开了 Effective C++ / More Effective C++ 警告,当我违反了其中一条规则时,我会重新阅读本书的部分内容。这确实帮助我在现实世界中理解这些规则。我发现它非常有益。
    【解决方案3】:

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

    【讨论】:

    • +1 建议使用试用版。我打算自己做。
    【解决方案4】:

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

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

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

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

    【讨论】:

    • 有一个用于 FindBugs 的 Eclipse 插件。
    • 你有 C++ 的交互式静态分析工具的例子吗?我从未见过,但我很想看看。
    • 我是 redlizards.com 的一名开发人员 - 我们制作 Goanna,这是一个 C/C++ 静态分析工具,它具有不同的版本,可在夜间构建中运行,并集成到 IDE(VS 和日食插件)。可能值得一看。
    【解决方案5】:

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

    【讨论】:

    • 这符合我的经验。三四年前我使用 PC-Lint 时,它太吵了,即使拨回去,它也抱怨太多没有问题的东西。
    • 这是在使用相当高级 C++ 功能的代码库中。
    【解决方案6】:

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

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

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

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

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

    编辑:

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

    【讨论】:

    • 最近我在公司开发一种新的硬件/软件产品,我很幸运地说服了负责人将一些编译器警告更改为错误。警告到错误的变化迫使每个人都摆脱了这些警告。
    • 此编译器标志更改是我更改“编码风格”和“流程”的最佳选择,而无需向所有人发送电子邮件授权。
    • 我认为我最快乐的日子之一是检查 60 个带有 /W4 的项目的更改 :-)
    • /W4 --> 出于好奇,您能详细介绍一下/W4吗?
    • /W4 将 Microsoft 编译器警告调到最高。对于 gcc,我使用了 15 个选项 :-)
    【解决方案7】:

    无论是不是 C++,发现真正错误的静态分析都是值得的。有些往往很嘈杂,但如果它们能够捕捉到细微的错误,例如有符号/无符号比较导致的优化会破坏您的代码或超出范围的数组访问,那么它们绝对值得付出努力。

    【讨论】:

      【解决方案8】:

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

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

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

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

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

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

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

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

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

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

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

      【讨论】:

      • C++ 的一个不错的特性是,内联函数和模板意味着在单个 TU 中可以获得大量信息。因此,一个好的静态分析工具可以对 TU 中可见的功能进行跨过程分析。
      • 我的主要观点是这些工具具有潜在的高采用成本,并且只能捕获有限的类错误。这意味着它们不是“通用”解决方案。它们对某些项目可能至关重要,而对另一些项目则浪费时间。使用它们应基于个人需要。
      【解决方案9】:

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

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

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

      【讨论】:

        【解决方案10】:

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

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

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

        【讨论】:

        • Coverity 只执行逐个文件的分析,所以如果你想分析源文件之间的函数如何交互,你需要雇佣几个人(因为这些工具无法执行完整程序分析).
        【解决方案11】:

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

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

        如果时间允许,我应该尽快写第 2 部分,但总的来说,请粗略计算一下是否值得:

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

        我个人的看法也是:

        • 尽早进行静态分析

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

          • 没有人喜欢被测试工程师或一些匿名工具告知 他们昨天做错了什么
          • 更少的调试让开发人员开心:-)
          • 提供了一种很好的方法来了解(微妙的)陷阱而不会感到尴尬

        【讨论】:

          【解决方案12】:

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

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

          1) 不要一下子打开所有东西,确定一组初始缺陷,打开这些分析并在整个代码库中修复它们。

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

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

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

          【讨论】:

            【解决方案13】:

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

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

            【讨论】:

              【解决方案14】:

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

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

              《Debian Linux 格式字符串漏洞大规模分析》 由卡尔陈,大卫瓦格纳, 加州大学伯克利分校, {夸尔,daw}@cs.berkeley.edu

              摘要:

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

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2023-03-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多