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

你将如何去C / C ++代码中的死代码检测? 我有一个相当大的代码基地工作,至less10-15%是死代码。 有没有任何基于Unix的工具来识别这个领域? 有些代码还使用了很多预处理器,可以自动进行处理吗?

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

一个stream行的gcc工具链是gcov,连同graphics前端lcov( http://ltp.sourceforge.net/coverage/lcov.php )。

如果使用gcc,则可以使用gcov支持进行编译,这是由'–coverage'标志启用的。 接下来,运行你的应用程序或运行你的testing套件与这个gcov启用构build。

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

运行后,您可以将所有覆盖率数据放在一起,并通过lcov工具包运行。 所有覆盖文件从不同的testing运行合并也是可能的,尽pipe有一点涉及。

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

当然,你需要仔细检查一下代码的部分是不是在任何情况下使用,很大程度上取决于你的testing如何执行代码库。 但至less,这将给出一个关于可能的死代码候选人的想法…

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

我认为,最近的版本,你会得到更好的结果,但我可能是错误的印象,这是他们一直在积极努力。 请注意,这是stream程分析,但我不相信它会告诉您有关“代码”,它已离开预处理器已经死了,因为这从来没有被编译器分析。 它也不会检测例如从不被调用的导出函数,或者特殊情况下的处理代码,因为没有任何东西用这个参数调用函数,所以你需要代码覆盖(并且运行functiontesting,而不是unit testing,unit testing应该有100%的代码覆盖率,因此就应用程序而言,执行代码path是“死的”。 不过,考虑到这些限制,这是一个简单的方法来开始在代码库中find最完全的bollixed例程。

此CERT公告列出了一些用于静态死代码检测的其他工具

您的方法取决于可用性(自动)testing。 如果您有一个您信任的testing套件来覆盖足够的function,那么您可以使用覆盖率分析,如之前的build议。

如果你不那么幸运,你可能想看看像SciTools的 “了解”这样的源代码分析工具,它可以帮助你使用大量内置的分析报告来分析你的代码。 我对这个工具的使用经验可以追溯到两年前,所以我不能给你太多的细节,但是我记得,他们有一个非常快速的错误修复和问题答案的支持。

我在静态源代码分析中find了一个页面,列出了许多其他工具。

如果这对你没有足够的帮助,而且你对find与预处理器相关的死代码特别感兴趣,我build议你发布一些关于代码的更多细节。 例如,如果它主要涉及#ifdef设置的各种组合,则可以编写脚本来确定(组合)设置并找出哪些组合从未实际构build等等。

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

如果您有“死代码”问题,您可能也有兴趣删除“备用代码”,即执行的代码,但不影响最终结果。 这要求您提供I / O函数的精确模型(您不希望删除似乎是“备用”但用作printf的参数的计算)。 Frama-C可以select指出备用代码。

Mozilla和Open Office都有自己的解决scheme。

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

 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()(即使在这个文件中它是无法访问的)也没有提到。 这种行为是正确的,虽然令人失望,因为编译器无法知道函数foo()在其他编译单元中没有声明为extern并从那里调用; 只有链接器可以肯定。

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

我们已经使用我们的DMS Software Reengineering Toolkit来完成Java代码的实现,通过parsing所有涉及的编译单元,为所有东西构build符号表并追踪所有引用。 没有引用且没有声明是外部API项目的顶级定义已经死亡。 这个工具也会自动去掉死代码,最后你可以select你想要的:死实体的报告,或者剥离这些实体的代码。

DMS还以各种方言parsingC ++(编辑2014年2月: 包括C ++ 14的MS和GCC版本[编辑2017年11月:现在C ++ 17] ),并build立所有必要的符号表。 追查死亡的参考资料将从这一点直截了当。 DMS也可以用来去除它们。 请参阅http://www.semanticdesigns.com/Products/DMS/DMSToolkit.html

舷窗覆盖工具将有所帮助。 虽然这不是免费的。