【问题标题】:Is there a way to detect when file dependencies are "accidentally" satisfied?有没有办法检测文件依赖关系何时“意外”得到满足?
【发布时间】:2011-10-07 01:25:29
【问题描述】:

假设有三个标头AAA.hBBB.hMyLib.hMyLib.h 需要同时包含 AAA.hBBB.h 才能正常工作。

现在,恰好BBB.h 也包含AAA.h,但这完全是由于实现,MyLib.h 不需要关心的细节。

但是,MyLib.h 的作者错误地忽略了包含AAA.h 并且从未注意到。据我所知,这通常不会导致错误或警告。后来,有人更改了BBB.h 的实现细节,使AAA.h 不再需要并因此被删除。现在 MyLib 无法编译,因为库 BBB 的内部结构发生了变化。

在这种情况下,有没有办法发出错误或警告?我怀疑(如果这甚至可能的话)在包含的标题中需要某种注释。

【问题讨论】:

  • 你是对的,它需要注释,因为有时标头被记录以包含其他标头,或者标头是通过包含其他文件在内部实现的。您不希望遇到很多误报,因为您的代码依赖于 /compiler/internals/stl_vector_impl.h 中定义的内容,而您的应用程序包含的所有内容都是 <vector>,或者用户定义的库遵循类似的组织。
  • GCC 有一个选项可以查看哪些标头包含哪些其他标头:stackoverflow.com/questions/5258826/…

标签: c header include


【解决方案1】:

我觉得公共接口头中最好避免依赖其他头,这样就不会出现这个问题。

公共接口标头不应包含不必要的定义。

在没有包含文件的情况下,有很多技巧可以做事。例如,如果您只需要一个指针(仅定义 typedef 的库会阻止这一点),您可以手动声明结构标记,并且您可以使用_Bool 而不是bool 来避免<stdbool.h>。遗憾的是,size_tuint32_t 等许多重要类型仅在标头中定义。

有些包甚至使用 configure 定义了自己的foo_uint32_t,因此它们不需要在其公共接口标头中包含<stdint.h>。这是相当棘手的,因为类型必须完全相同以避免混淆:即使sizeof(unsigned int) == sizeof(unsigned long) == 4 它们是不同的类型。因此,它可能不值得。

【讨论】:

    【解决方案2】:

    您正在说明为什么包含标头作为导入命名空间的方法很糟糕。

    我看到的唯一解决方案是纪律。标准库函数要求您包含适当的标头,您的项目应采用相同的标准。诸如MyLib.h 之类的标头应该只包含它定义的类型及其函数原型。如果它需要使用某种类型来完成它的工作,则应该明确包含标题,因此如果它需要来自AAA 的定义,它应该包括AAA.h,如果它需要来自BBB 的一些定义,它应该包括@ 987654325@,同样任何实现文件(比如说MyLib.c)都应该明确地包含它使用的任何定义的所有头文件,无论是否确定MyLib.h 也包含它们。 永远不要假设一个标头通过包含其他标头来隐式定义任何内容

    这很容易使用 IDE 进行检查,它通常会告诉您名称的定义位置,因此您可以轻松确定要使用的包含文件。可能有一些工具可以进行这种检查。

    【讨论】:

      猜你喜欢
      • 2019-10-15
      • 1970-01-01
      • 2016-07-10
      • 1970-01-01
      • 2020-05-12
      • 2017-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多