如何在代码库中找到未引用的类

How to find unreferenced classes in a codebase

本文关键字:引用 代码      更新时间:2023-10-16

我们正处于一个开发阶段,其中有很多代码可能是短暂的,因为它实际上是脚手架,在某些时候会被其他东西取代,但通常会继续存在并被遗忘。

有什么好的技术可以找到代码库中不使用的类吗?显然会有很多误报(例如库类:您可能没有使用所有的标准容器,但您想知道它们在那里),但如果它们按目录列出,那么它可能更容易一眼看到。

我可以编写一个脚本,对所有class XXX进行greps,然后再次搜索所有实例,但是必须省略定义类方法的cpp文件的结果。这也会非常慢- 0 (N^2)的代码库中的类的数量

代码覆盖工具在这里不是一个真正的选择,因为这是一个GUI,不能轻易地通过编程调用所有功能。

平台为Visual Studio 2013或Xcode/clang

编辑:我不相信这是一个重复的死代码问题。尽管存在重叠,但识别死代码或不可达代码与查找未引用的类并不完全相同。

如果你在linux上,那么你可以使用g++来帮助你。

我将假设只有当类的实例被创建时,我们才认为它被使用。因此,与其只查找类名,还可以查找对构造函数的调用。

struct A
{
  A () { }
};
struct B
{
  B () { }
};
struct C
{
  C () { }
};
void bar ()
{
  C c;
}
int main ()
{
  B b;
}

至少在linux上,在二进制文件上运行nm有以下混乱的名称:

00000000004005bc T _Z3barv
00000000004005ee W _ZN1BC1Ev
00000000004005ee W _ZN1BC2Ev
00000000004005f8 W _ZN1CC1Ev
00000000004005f8 W _ZN1CC2Ev

可以立即看出没有调用'A'的构造函数。

使用从这个SO答案稍微修改的信息,我们也可以得到g++删除不使用的函数调用图:

结果是:

00000000004005ba W _ZN1BC1Ev
00000000004005ba W _ZN1BC2Ev

因此,至少在linux上,您可以判断最终可执行文件中既不需要A也不需要C。

我编写了一个简单的shell脚本,它至少有助于将注意力集中在引用最少的类上。我做了一个假设,如果一个类没有被使用,那么它的名字仍然会出现在一个或两个文件中(在头文件中的声明和在cpp文件中的定义)。因此,脚本使用标签在源目录中搜索类声明。然后,对于每个类,它执行递归grep以查找提到该类的所有文件(注意:您可以指定不同的类和用法目录),最后它将文件计数和类名写入一个文件并按数字顺序显示它们。然后,您可以查看只有1或2次提及的所有条目。

#!/bin/bash
CLASSDIR=${1:-}
USAGEDIR=${2:-}
if [ "${CLASSDIR}" = "" -o "${USAGEDIR}" = "" ]; then 
    echo "Usage: find_unreferenced_classes.sh <classdir> <usagedir>"
    exit 1
fi
ctags --recurse=yes --languages=c++ --c++-kinds=c -x $CLASSDIR | awk '{print $1}' | uniq > tags
[ -f "counts" ] && rm counts
for class in `cat tags`;
do
    count=`grep -l -r $class $USAGEDIR --include=*.h --include=*.cpp | wc -l`
    echo "$count $class" >> counts
done
sort -n counts
样本输出:

1 SomeUnusedClassDefinedInHeader
2 SomeUnusedClassDefinedAndDeclaredInHAndCppFile
10 SomeClassUsedLots