用于查找未使用的包含标头的工具?

Nic*_*tin 70 c++ coding-style header-files

我知道PC-Lint可以告诉你包含但未使用的标题.有没有其他工具可以做到这一点,最好是在Linux上?

我们拥有一个庞大的代码库,在过去的15年中已经看到了大量的功能,但是当功能从一个实现文件移动到另一个实现文件时,很少会删除剩余的#include指令,这一点让我们陷入了相当糟糕的状态.显然我可以去除所有#include指令并让编译器告诉我哪些重新包含,但是我宁愿反过来解决问题 - 找到未使用的指令 - 而不是重建已使用的指令列表.

Ric*_*den 30

免责声明:我的日常工作是为一家开发静态分析工具的公司工作.

如果大多数(如果不是全部)静态分析工具没有某种形式的标头使用检查,我会感到惊讶.您可以使用维基百科页面获取可用工具列表,然后通过电子邮件向公司询问.

在评估工具时可能会考虑以下几点:

对于函数重载,您希望所有包含重载的标头都可见,而不仅仅是包含重载决策选择的函数的标头:

// f1.h
void foo (char);

// f2.h
void foo (int);


// bar.cc
#include "f1.h"
#include "f2.h"

int main ()
{
  foo (0);  // Calls 'foo(int)' but all functions were in overload set
}
Run Code Online (Sandbox Code Playgroud)

如果你采用强力方法,首先删除所有标题,然后重新添加它们直到它编译,如果先添加'f1.h',那么代码将编译,但程序的语义已经改变.

当您具有部分和专业化时,类似的规则也适用.无论是否选择专业化都无关紧要,您需要确保所有专业化都可见:

// f1.h
template <typename T>
void foo (T);

// f2.h
template <>
void foo (int);

// bar.cc
#include "f1.h"
#include "f2.h"


int main ()
{
  foo (0);  // Calls specialization 'foo<int>(int)'
}
Run Code Online (Sandbox Code Playgroud)

对于过载示例,强力方法可能导致仍然编译但具有不同行为的程序.

您可以注意的另一种相关类型的分析是检查类型是否可以向前声明.考虑以下:

// A.h
class A { };

// foo.h
#include "A.h"
void foo (A const &);

// bar.cc
#include "foo.h"

void bar (A const & a)
{
  foo (a);
}
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,'A'的定义不是必需的,因此可以更改头文件'foo.h',使其只有'A'的前向声明:

// foo.h
class A;
void foo (A const &);
Run Code Online (Sandbox Code Playgroud)

这种检查还减少了标头依赖性.


And*_*y C 22

这是一个执行它的脚本:

#!/bin/bash
# prune include files one at a time, recompile, and put them back if it doesn't compile
# arguments are list of files to check
removeinclude() {
    file=$1
    header=$2
    perl -i -p -e 's+([ \t]*#include[ \t][ \t]*[\"\<]'$2'[\"\>])+//REMOVEINCLUDE $1+' $1
}
replaceinclude() {
   file=$1
   perl -i -p -e 's+//REMOVEINCLUDE ++' $1
}

for file in $*
do
    includes=`grep "^[ \t]*#include" $file | awk '{print $2;}' | sed 's/[\"\<\>]//g'`
    echo $includes
    for i in $includes
    do
        touch $file # just to be sure it recompiles
        removeinclude $file $i
        if make -j10 >/dev/null  2>&1;
        then
            grep -v REMOVEINCLUDE $file > tmp && mv tmp $file
            echo removed $i from $file
        else
            replaceinclude $file
            echo $i was needed in $file
        fi
    done
done
Run Code Online (Sandbox Code Playgroud)


Ton*_*vel 5

看看Dehydra.

来自网站:

Dehydra是一种轻量级,可编写脚本的通用静态分析工具,能够对C++代码进行特定于应用程序的分析.从最简单的意义上讲,Dehydra可以被认为是一种语义grep工具.

应该可以提出一个检查未使用的#include文件的脚本.


Cha*_*nce 5

Google 的cppclean似乎在查找未使用的头文件方面做得不错。我刚开始使用它。它会产生一些误报。它经常会在头文件中发现不必要的包含,但它不会告诉您的是您需要关联类的前向声明,并且需要将包含移动到关联的源文件中。

  • 今天我的文件我可以不用`#include "baz.h"`。明天,也许不会。假设 `bar.h` 是你的责任,你也在删除不需要的头文件。你`bar.h` 不需要`baz.h`,所以你从`bar.h` 中删除无关的`#include "baz.h"`。您刚刚破坏了任何附加在无关的 `#include` 上的代码。解决方案不是依赖这种捎带。如果您的文件使用了在别处定义的某些功能,则`#include` 是定义该功能的文件。不要让其他标题为您做`#include`。 (3认同)