带有标头保护的对象文件

Object Files with Header Guards

本文关键字:对象 文件 保护      更新时间:2023-10-16

我对包含头的对象文件有点困惑。如果头保护程序包含在多个对象文件中,我看不出它们是如何保护您的。

例如:

main.o <- main.cpp class.h
class.o <- class.cpp class.h
main.exe <- main.o class.o

难道每个对象文件都包含类.h,从而使可执行文件有两个副本吗?

你是对的,这没有问题。标头保护可防止编译器看到两个副本,但不会影响链接器。事实上,链接器依赖于存在两个副本这一事实。毕竟,它把这两者联系在一起。

对象文件不包含标头;它们包含编译器。但你提出的观点是有效的:标题中的任何内容都可能在最终代码中重复多次。粗略地说,我们可以区分两类:

  1. 声明不会创建任何可能在编译器输出:typedef之类的东西,或者模板以及类定义。该标准允许重复的定义,前提是他们都是;完全相同";。

  2. 不允许重复的声明,以及不应该在页眉中。比如变量和函数。

在实践中,它有点复杂,模板可能会被实例化在几个不同的源中的相同类型上,以及实例化模板的函数可以是一个函数。或者编译器可能无法内联内联函数。通常的处理方法是编译器在每个翻译单元中生成函数,并且链接器把复制品扔掉。(事实上,大多数链接者不会检查它们确实是重复的。他们只是把所有的都扔了,只有一个是被选中的或多或少是随机的。)

头保护防止编译器处理头文件两次(这可能会产生无益的错误,因为一旦定义了类,就不允许重新定义它)。

如果头文件包含编译器实际需要为其生成代码(或数据)的内容,则该将出现在每个对象文件中。

然后由链接器来处理,这可能会导致链接器错误(例如,如果您包含了一个函数的代码而没有说它是内联的,则会导致同一函数的两个实例),或者没有问题(当您说所述函数是内联的时,在这种情况下,链接器将只选择一个)。

大多数情况下,标头只包含函数原型(不生成代码)、类定义(不生成任何代码)内联函数定义或外部引用。其中最后2个将在对象文件中生成需要由链接器处理的内容。