【问题标题】:Enforce explicit (direct) #include statements with GCC使用 GCC 强制执行显式(直接)#include 语句
【发布时间】:2013-09-30 18:51:27
【问题描述】:

我想知道是否可以使用 GCC 强制执行直接 #include 要求。假设我有这些文件:

abc.h:

typedef struct {
   int useful;
} str;

file1.h:

#include <abc.h>
#ifndef GUARD
#define GUARD

#include <deh.h>

typedef struct {
   int useful;
} str2;

#endif

file2.h:

#ifndef GUARD2
#define GUARD2
#include <file1.h>

void a_function (str*  my_str);
void a_function2(str2* my_str);

#endif

问题是“file2.h”正在使用“abc.h”中定义的“str”。假设“file1.h”是由某些 Linux 系统上的系统提供的。我无法控制“file1.h”的内容。如果可能包括也可能不包括,它可能在内部也可能不包括警卫,它可能会或可能不会随着时间的推移而改变。

问题在于支持多个发行版和系统。如果 file2.h 不小心使用了 "str" 而没有 include ,它可能在大多数系统上仍然可以编译,但在其他系统上可能会失败,或者将来当 "file1.h" 更改时。

有没有办法强制 GCC(或 LLVM)只使用在 file2.h 中直接定义的类型?我知道“#include”只是包含,所以编译器内部可能不会在预处理器阶段之后意识到这些问题,但是,我想知道这目前是否可行,如果可以,如何实现?

我在使用“普通”Linux 发行版时遇到过这个问题,但在早期的 Android NDK 版本中情况更糟。

【问题讨论】:

  • 好吧,为什么不先包含 abc.h 呢?
  • 更好的是,file2.h 应该 #include 什么都没有。我觉得这个问题不清楚。 在这种情况下你希望编译器做什么?
  • @Beta:对于“扁平化包含并将它们全部放在主源文件中”的方法肯定没有达成共识。这就是你所提倡的吗?
  • @zneak:问题在于开发人员何时忘记包含所有必需的文件。在某些情况下,因为它们是间接包含的,所以无论如何它都会编译,因此开发人员不会注意到。当您无法控制的文件包含间接包含的文件时,这会导致问题。在这种情况下,当该文件的第三方所有者更改它时,可能会导致编译错误。
  • @BenVoigt:不,我是说省略(而不是扩展)#include 语句是实现 OP 既定目标的明智方式。

标签: c++ c gcc compiler-errors compiler-warnings


【解决方案1】:

不,#include 指示编译器将其他文件的内容视为放置在 #include 指令中的内容 - 您要求以某种不同的方式处理其他文件的内容。

在这种情况下,您最大的希望是使用静态分析工具执行依赖分析,并检查通过间接(嵌套)包含获得的类型(或函数或对象)是否没有直接依赖关系。

免费的doxygen 文档工具提取有关包含和依赖关系的信息,并以 XML 格式提供。当然,就重载解析和模板处理而言,它不如真正的编译器准确。我确信有付费工具会更准确(用户 Ira Baxter 不时弹出提及他的公司销售的商业产品、DMS Toolkit 或类似的东西,听起来它会得到这些信息)。但我猜 doxygen 将为您提供大多数“正常”代码的正确结果。

【讨论】:

    【解决方案2】:

    C++ 语言中没有任何东西可以验证是否正确包含所有标头。但是,有基于clanginclude-what-you-use。我还没有尝试过使用它,但它似乎是你正在寻找的方向。对于 C,实现一个分析器检测依赖关系并报告缺少的直接包含似乎是相当简单的。由于需要检测模板实例化的依赖关系,在 C++ 中尝试相同的操作会变得有些困难。

    根据上周在 C++ 委员会会议上的讨论,重构源代码和标头以正确包含实际使用的内容可能对未来 C++ 中的module support 有所帮助。

    【讨论】:

    • "include-what-you-use 的主要目标是......尽可能用 forward-declares 替换 #includes" 不确定这是这个问题的要求,甚至是一个好的主意。使用前向声明有一些优点,但它们是一种代码重复形式,使用它们时必须注意不要违反单一定义规则。
    • OTOH 我敢肯定,include-what-you-use 是这个问题所需的静态分析的良好基础。可能只是不能按原样使用。
    猜你喜欢
    • 1970-01-01
    • 2017-10-08
    • 2013-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多