C++:链接库两次,全局构造函数运行两次吗?

C++: link library twice, are global constructors run twice?

本文关键字:两次 构造函数 运行 全局 链接 C++      更新时间:2023-10-16

如果我有一个库foo,里面有一些静态初始化代码,并且链接情况如下:

executable -> libShared.so (dynamic linking)
executable -> libFoo.a (static linking)
libShared.so -> libFoo.a (static linking)

这是否会导致静态初始化代码运行两次 - 如果它有副作用,可能会做两个不同的可见事情?

libShared.so 只导出自己的符号,而不导出任何libFoo.a,这是正确的。但是在这个过程中有两个libFoo.a的副本,有效地彼此分开命名空间。我的理解是否正确 - 会有一个重复的初始化步骤?

(当然,正确的方法是让libFoo.a不做任何事情,例如在其静态初始值设定项中创建可见的副作用,但让我们假设船已经航行了......

是的,构造函数将运行两次。生成可执行文件或共享库时,将创建一个帮助程序方法,该方法枚举要构造的所有全局变量并调用其初始值设定项(ISO C++允许其他方法,但不用于具有共享库的系统(。加载可执行文件和共享库时,将调用这些帮助程序。

现在你碰巧有两个这样的方法来初始化内存的两个不同部分。这将创建两个对象,它们的地址会有所不同。

如果可执行文件只有全局的extern声明,这将有所不同,但显然它不能 - 它使用相同的静态库。

全局对象的析构函数有自己的辅助方法,工作原理大致相同。

静态库只是对象文件的串联 - 其中没有代码来运行静态对象的构造函数,除非您显式提供此类代码。因此,静态库中的静态对象不会让构造函数运行两次,甚至可能运行一次。此外,由于大多数链接器搜索静态库的方式,多次链接到它们是一种非常常见的做法。