我有遗留的c++代码,我应该删除不使用的代码。问题是代码库很大。

我如何才能知道哪些代码从未被调用/从未被使用?


当前回答

我通常找没用的东西的方法是

确保构建系统正确地处理依赖项跟踪 设置第二个监视器,使用全屏终端窗口,运行重复构建并显示第一个满屏的输出。watch "make 2>&1"倾向于在Unix上做到这一点。 在整个源代码树上运行查找和替换操作,添加“//?”“在每一行的开头 通过删除相应行中的"//?"来修复编译器标记的第一个错误。 重复操作,直到没有错误。

这是一个有点漫长的过程,但确实能得到很好的结果。

其他回答

我自己没有使用过cppcheck,但它声称可以找到未使用的函数。这也许不能完全解决问题,但可能是个开始。

有两种未使用的代码:

局部路径,即在某些函数中,某些路径或变量未使用(或使用但没有任何意义,如写入但从未读取) 全局的:永远不会调用的函数,永远不会访问的全局对象

对于第一种类型,一个好的编译器可以帮助:

-Wunused (GCC, Clang)应该警告未使用的变量,Clang未使用的分析器甚至已经增加到警告从未读取的变量(即使使用)。 -Wunreachable-code(旧的GCC,在2010年被移除)应该警告从未被访问的局部块(它发生在早期返回或条件总是计算为true时) 据我所知,没有选项可以警告未使用的catch块,因为编译器通常不能证明没有异常将被抛出。

对于第二种,要困难得多。静态地,它需要整个程序的分析,即使链接时间优化实际上可以删除死代码,在实践中,程序在执行时已经进行了如此多的转换,以至于几乎不可能向用户传递有意义的信息。

因此有两种方法:

The theoretic one is to use a static analyzer. A piece of software that will examine the whole code at once in great detail and find all the flow paths. In practice I don't know any that would work here. The pragmatic one is to use an heuristic: use a code coverage tool (in the GNU chain it's gcov. Note that specific flags should be passed during compilation for it to work properly). You run the code coverage tool with a good set of varied inputs (your unit-tests or non-regression tests), the dead code is necessarily within the unreached code... and so you can start from here.

如果您对这个主题非常感兴趣,并且有时间和意愿自己开发一个工具,我建议您使用Clang库来构建这样一个工具。

使用Clang库获取AST(抽象语法树) 从入口点开始执行标记-清除分析

因为Clang将为您解析代码,并执行重载解析,所以您不必处理c++语言规则,并且您将能够集中精力处理手头的问题。

然而,这种技术不能识别未使用的虚拟覆盖,因为它们可能由您无法推理的第三方代码调用。

我通常找没用的东西的方法是

确保构建系统正确地处理依赖项跟踪 设置第二个监视器,使用全屏终端窗口,运行重复构建并显示第一个满屏的输出。watch "make 2>&1"倾向于在Unix上做到这一点。 在整个源代码树上运行查找和替换操作,添加“//?”“在每一行的开头 通过删除相应行中的"//?"来修复编译器标记的第一个错误。 重复操作,直到没有错误。

这是一个有点漫长的过程,但确实能得到很好的结果。

我真的没有使用过任何工具做这样的事情…但是,就我所看到的所有答案,没有人说过这个问题是不可计算的。

这是什么意思呢?这个问题不能用计算机上的任何算法解决。这个定理(这样的算法不存在)是图灵停止问题的一个推论。

你将使用的所有工具都不是算法,而是启发式(即不是精确的算法)。他们不会给你所有没有使用的代码。

我不认为它可以自动完成。

即使使用代码覆盖工具,也需要提供足够的输入数据来运行。

可能是非常复杂和昂贵的静态分析工具,如Coverity的或LLVM编译器可能会有所帮助。

但我不确定,我更喜欢手动代码审查。

更新

嗯. .不过,仅删除未使用的变量和未使用的函数并不难。

更新

看了其他人的回答和评论后,我更加坚定地认为这是不可能的。

您必须了解代码以获得有意义的代码覆盖率度量,如果您知道大量的手动编辑将比准备/运行/检查覆盖率结果更快。