小编典典

我如何知道代码中的哪些部分从未使用过?

all

我有遗留的 C++ 代码,我应该从中删除未使用的代码。问题是代码库很大。

如何找出从未调用/从未使用过的代码?


阅读 85

收藏
2022-04-14

共1个答案

小编典典

有两种未使用的代码:

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

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

  • -Wunused(GCC,Clang)应该警告未使用的变量,Clang 未使用的分析器甚至已经增加以警告从未读取的变量(即使使用过)。
  • -Wunreachable-code(旧 GCC,于 2010 年删除)应该警告从未访问过的本地块(它发生在早期返回或总是评估为 true 的条件下)
  • 我知道没有选项可以警告未使用catch的块,因为编译器通常无法证明不会引发异常。

对于第二种,难度要大得多。静态地,它需要对整个程序进行分析,即使链接时间优化实际上可能会删除死代码,但实际上程序在执行时已经发生了很大的变化,几乎不可能向用户传达有意义的信息。

因此有两种方法:

  • 理论上是使用静态分析仪。一个软件,可以一次非常详细地检查整个代码并找到所有的流程路径。在实践中,我不知道任何可以在这里工作的东西。
  • 实用的方法是使用启发式方法:使用代码覆盖工具(在 GNU 链中它是gcov. 请注意,在编译期间应传递特定标志以使其正常工作)。您使用一组良好的不同输入(您的单元测试或非回归测试)运行代码覆盖工具,死代码必然在未到达的代码中......所以您可以从这里开始。

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

  1. 使用 Clang 库获取 AST(抽象语法树)
  2. 从入口点开始执行标记和扫描分析

因为 Clang 将为您解析代码并执行重载解析,所以您不必处理 C++ 语言规则,您将能够专注于手头的问题。

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

2022-04-14