传统C / C ++项目中的死代码检测

时间:2008-10-23 09:18:25

标签: c++ automation static-analysis legacy-code dead-code

您如何在C / C ++代码中进行死代码检测?我有一个非常大的代码库可供使用,至少10-15%是死代码。有没有基于Unix的工具来识别这个区域?有些代码仍然使用了很多预处理器,可以自动处理那个吗?

8 个答案:

答案 0 :(得分:30)

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

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

如果您使用gcc,则可以使用gcov支持进行编译,该支持由'--coverage'标志启用。接下来,运行您的应用程序或使用此gcov启用的版本运行您的测试套件。

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

运行后,您可以将所有覆盖数据放在一起并通过lcov工具包运行。虽然有点涉及,但也可以合并来自不同测试运行的所有覆盖文件。

无论如何,你最终会得到一组很好的网页,显示一些覆盖信息,指出没有覆盖的代码片段,因此没有使用。

当然,您需要仔细检查代码的各个部分是否在任何情况下都没有使用,而且很大程度上取决于您的测试执行代码库的程度。但至少,这会给出关于可能的死码候选者的想法......

答案 1 :(得分:17)

使用-Wunreachable-code在gcc下编译它。

我认为版本越近越好,你会得到更好的结果,但我的印象可能是错误的,这是他们一直在积极研究的。请注意,这会进行流分析,但我不相信它会告诉您“离开预处理器时已经死亡的”代码,因为它从未被编译器解析过。它也不会检测到例如从未被调用过的导出函数,或者特殊情况处理代码,这些都是不可能的,因为没有任何东西用该参数调用函数 - 你需要代​​码覆盖(并运行功能测试,而不是单元测试。单元测试是假设具有100%的代码覆盖率,因此就应用程序而言,执行“死”的代码路径。尽管如此,考虑到这些限制,这是一种简单的方法来开始在代码库中找到最完整的bollixed例程。

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

答案 2 :(得分:4)

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

如果您不是那么幸运,您可能需要查看像SciTools这样的源代码分析工具。了解这可以帮助您使用大量内置分析报告来分析代码。我使用该工具的经验可以追溯到2年前,所以我不能给你太多细节,但我记得的是,他们得到了令人印象深刻的支持,错误修复和问题答案的周转时间非常快。

我在static source code analysis上找到了一个页面,其中列出了许多其他工具。

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

答案 3 :(得分:4)

MozillaOpen Office都有自己开发的解决方案。

答案 4 :(得分:4)

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

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)

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

如果您遇到“死代码”问题,您可能也会感兴趣 删除“备用代码”,执行但不执行的代码 有助于最终结果。这需要你提供 准确的I / O功能模型(你不会想要的 删除似乎是“备用”的计算但是 用作printf的参数。 Frama-C有一个指出备用代码的选项。

答案 6 :(得分:3)

这样的死代码分析需要对整个项目进行全局分析。您无法通过单独分析翻译单元来获取此信息(如果它们完全位于单个翻译单元中,您可以检测到死实体,但我认为这不是您真正想要的)。

我们已经使用我们的DMS软件重新设计工具包来实现Java代码的完全实现,通过一次解析所涉及的所有编译单元,为所有内容构建符号表并追踪所有引用。没有引用且没有声称是外部API项的顶级定义已经死亡。此工具还会自动删除死代码,最后您可以选择所需内容:死实体的报告或剥离这些实体的代码。

DMS还以各种方言解析C ++(EDIT 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

答案 7 :(得分:1)

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