免责声明:我的日常工作是在一家开发静态分析工具的公司工作。
如果大多数(如果不是全部)静态分析工具没有某种形式的标头使用情况检查,我会感到惊讶。你可以使用this维基百科页面获取可用工具的列表,然后向公司发送电子邮件询问他们。
评估工具时您可能需要考虑的一些要点:
对于函数重载,您希望包含重载的所有标头都可见,而不仅仅是包含由重载解析选择的函数的标头:
// 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
}
如果采用暴力方法,首先删除所有标头,然后重新添加它们直到编译,如果先添加“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)'
}
对于重载示例,暴力方法可能会导致程序仍然可以编译但具有不同的行为。
您可以关注的另一种相关分析类型是检查类型是否可以前向声明。考虑以下:
// 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);
}
在上面的示例中,不需要定义“A”,因此可以更改头文件“foo.h”,使其仅具有“A”的前向声明:
// foo.h
class A;
void foo (A const &);
这种检查还减少了标头依赖性。