【问题标题】:How to find unreferenced classes in a codebase如何在代码库中查找未引用的类
【发布时间】:2014-08-01 05:38:08
【问题描述】:

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

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

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

代码覆盖工具在这里并不是一个真正的选择,因为它的 GUI 不能以编程方式轻松调用所有功能。

平台是 Visual Studio 2013 或 Xcode/clang

编辑:我不认为这是死代码问题的重复。尽管存在重叠,但识别死代码或无法访问的代码与查找未引用的类并不完全相同。

【问题讨论】:

  • 这听起来类似于死代码问题 - stackoverflow.com/questions/162551/…。这是关于 Java 的,但我怀疑有什么真正的区别。实际上,有一个 C++ 死代码问题 - 请参阅 stackoverflow.com/questions/321241/dead-code-identification-c
  • 也许,如果您可以自动创建项目的 uml 图,其中包括调用 hirachies,您可以执行目视检查并查找所有断开连接的节点。
  • @sashoalm - 有几种可能性,谢谢。
  • @MikeMB - 对于大约 500kLOC 的代码库,每次调用的任何 UML 图都将是巨大的,所以我不认为这是一个可扩展的解决方案。
  • @The_mandrill:是也不是。我不知道是否有任何工具可以生成这样的图表(Visual Studio 的代码图非常适合小型项目)。另一方面,分析这样的图表应该是可能的,原因有两个:首先,一个合适的工具无论如何都会单独显示断开的节点或集群,其次,如果你有例如访问 xml 表示,应该很容易编写一个脚本来查找没有传入边缘的所有节点。但当然,这只是我个人的猜测,因为我还没有参与过大型项目。

标签: c++ static-analysis


【解决方案1】:

如果您使用的是 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 answer 的稍微修改的信息,我们还可以获取g++ 来删除未使用的函数调用图:

结果:

00000000004005ba W _ZN1BC1Ev
00000000004005ba W _ZN1BC2Ev

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

【讨论】:

    【解决方案2】:

    我想出了一个简单的 shell 脚本,它至少有助于将注意力集中在引用最少的类上。我假设如果一个类没有被使用,那么它的名字仍然会出现在一两个文件中(头文件中的声明和 cpp 文件中的定义)。因此该脚本使用 ctags 在源目录中搜索类声明。然后对于每个类,它执行递归 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
    

    【讨论】:

      猜你喜欢
      • 2022-07-21
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2014-09-26
      • 2020-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多