代码之家  ›  专栏  ›  技术社区  ›  Nazgob

遗留C/C++项目中的死代码检测

  •  68
  • Nazgob  · 技术社区  · 16 年前

    你将如何在C/C++代码中进行死代码检测?我有一个相当大的代码库可以使用,至少有10-15%是死代码。有没有基于Unix的工具来识别这个领域?有些代码仍然使用大量的预处理器,自动处理能处理吗?

    8 回复  |  直到 7 年前
        1
  •  30
  •   Johan    16 年前

    您可以为此使用代码覆盖率分析工具,并在代码中查找未使用的点。

    GCC工具链的一个流行工具是GCOV,以及图形化的前端LCOV。( http://ltp.sourceforge.net/coverage/lcov.php )

    如果使用gcc,则可以使用gcov支持编译,该支持由“--coverage”标志启用。接下来,运行您的应用程序或使用这个支持gcov的构建运行您的测试套件。

    基本上,gcc在编译期间会发出一些额外的文件,并且应用程序在运行时也会发出一些覆盖率数据。您必须收集所有这些(.gcdo和.gcda文件)。我不想在这里详细介绍,但您可能需要设置两个环境变量来以一种明智的方式收集覆盖率数据:gcov_prefix和gcov_prefix_strip…

    运行之后,您可以将所有覆盖率数据放在一起,并通过lcov工具套件运行它。合并来自不同测试运行的所有覆盖率文件也是可能的,尽管有点复杂。

    不管怎样,你最终得到了一组很好的网页,显示了一些覆盖率信息,指出了一些没有覆盖率的代码,因此没有被使用。

    当然,您需要仔细检查代码的各个部分是否在任何情况下都不使用,并且很大程度上取决于您的测试对代码库的锻炼程度。但至少,这将给出一个关于可能死代码候选的想法…

        2
  •  17
  •   mbq    14 年前

    使用-wunreachable代码在gcc下编译它。

    我认为这个版本越新,效果越好,但我可能错了,我认为这是他们一直在积极努力的事情。注意,这确实是流分析,但我不相信它告诉你“代码”在离开预处理器时已经死了,因为编译器从未分析过它。它也不会检测到,例如,从未调用过的导出函数,或者由于没有任何东西调用过具有该参数的函数而导致无法执行的特殊情况处理代码——您需要代码覆盖范围(并运行功能测试,而不是单元测试)。单元测试是 想象上的 拥有100%的代码覆盖率,因此,就应用程序而言,执行“死”的代码路径)。尽管如此,考虑到这些限制,开始在代码库中查找最完全混乱的例程是一种简单的方法。

    This CERT advisory lists some other tools for static dead code detection

        3
  •  4
  •   andreas buykx    16 年前

    您的方法取决于可用性(自动化)测试。如果您有一个信任的测试套件来覆盖足够的功能,那么您可以使用覆盖率分析,正如前面的答案已经建议的那样。

    如果你不是那么幸运的话,你可能想看看源代码分析工具,比如 SciTools '了解这可以帮助您使用许多内置分析报告分析代码。我在这个工具上的经验可以追溯到两年前,所以我不能给你太多细节,但是我记得他们有一个令人印象深刻的支持,错误修复和问题解答的周转时间非常快。

    我在上找到一页 static source code analysis 这也列出了许多其他工具。

    如果这对您也没有足够的帮助,并且您对查找与预处理器相关的死代码特别感兴趣,那么我建议您发布关于代码的更多详细信息。例如,如果它主要与ifdef设置的各种组合相关,您可以编写脚本来确定(组合)设置并找出实际上从未构建的组合,等等。

        4
  •  4
  •   Thomas L Holaday    16 年前

    G++4.01-Wunreachable代码警告函数中无法访问的代码,但不警告未使用的函数。

    int foo() { 
        return 21; // point a
    }
    
    int bar() {
      int a = 7;
      return a;
      a += 9;  // point b
      return a;
    }
    
    int main(int, char **) {
        return bar();
    }
    

    G++4.01将发出关于B点的警告,但是不要说关于foo()(A点)的任何内容,即使它在这个文件中是不可访问的。这种行为是正确的,尽管令人失望,因为编译器不知道函数foo()没有在其他编译单元中声明为extern并从中调用;只有链接器可以确定。

        5
  •  4
  •   Pascal Cuoq    11 年前

    仅用于C代码,并假定整个项目的源代码 可用,使用开源工具启动分析 Frama-C . 在GUI中显示红色的程序的任何语句都是 死代码。

    如果你有“死代码”问题,你也可能对 删除已执行但未执行的“备用代码” 为最终结果做出贡献。这需要你提供 I/O函数的精确建模(您不希望 删除一个看似“备用”但 它被用作 printf )FRAMA-C可以选择指出备用代码。

        6
  •  4
  •   Max Lybbert    7 年前

    两个 Mozilla Open Office 拥有本土解决方案。

        7
  •  3
  •   Ira Baxter    7 年前

    这种死代码分析需要对整个项目进行全局分析。你不能通过单独分析翻译单元来获得这些信息(如果完全在一个翻译单元中,你就可以检测出死实体,但我认为这不是你真正想要的)。

    我们已经使用我们的DMS软件再工程工具包来实现Java代码的准确,通过对所有涉及的编译单元进行解析,为所有事物建立符号表,并追踪所有引用。没有引用和声明为外部API项的顶级定义已失效。这个工具还自动删除死代码,最后您可以选择所需的内容:死实体的报告,或者从这些实体中删除的代码。

    DMS还分析了各种方言中的C++(编辑FEB 2014: including MS and GCC versions of C++14 [EDIT Nov 2017: now C++17] )并建立所有必要的符号表。从这一点上,追踪死引用是很简单的。DMS也可以用来将它们剥离出来。见 http://www.semanticdesigns.com/Products/DMS/DMSToolkit.html

        8
  •  1
  •   Ashwin    16 年前

    Bullseye 覆盖工具会有所帮助。但这不是免费的。