10

我习惯于认为全局/静态类成员的所有初始化都发生在 main() 的第一行之前。但我最近在某处读到该标准允许稍后进行初始化以“协助动态加载模块”。在动态链接时我可以看到这是真的:我不希望在我 dlopen'ed 库之前初始化库中的全局初始化。但是,在一组静态链接在一起的翻译单元(我的应用程序的直接 .o 文件)中,我会发现这种行为非常不直观。这只是在动态链接时才延迟发生还是可以随时发生?(或者我读错了什么?;)

4

4 回答 4

6

该标准在 3.6.2/3 中有以下内容:

命名空间范围的对象的动态初始化(8.5、9.4、12.1、12.6.1)是否在main的第一条语句之前完成是实现定义的。如果初始化延迟到 main 的第一个语句之后的某个时间点,它应该发生在第一次使用与要初始化的对象相同的翻译单元中定义的任何函数或对象之前。

但是 o当然,您永远无法正式确定初始化何时发生,因为初始化将在您访问变量之前发生!如下:

// t1.cc
#include <iostream>
int i1 = 0;

int main () {
  std::cout << i1 << std::endl

// t2.cc
extern int i1;
int i2 = ++i1;

我可以确认 g++ 4.2.4 至少似乎在 main 之前执行了“i2”的初始化。

于 2009-08-06T14:56:46.943 回答
1

想要用该规则解决的问题是动态加载问题。津贴不限于动态加载,正式可能发生在其他情况下。我不知道将它用于动态加载以外的任何实现。

于 2009-08-06T14:59:48.560 回答
0

让我们回顾一个伪代码:

在 DLL 中:

static int ItsDllVar = 1;
int EXPORTED_FUNCTION() { return ItsDllVar; }

在应用中:

static int AppVar1 = 2;
static int AppVar2 = EXPORTED_FUNCTION() + AppVar1;

所以根据静态初始化 AppVar2 得到 1+2=3

适用于局部静态变量的延迟初始化(与 DLL 无关)

int f()
{
    static int local_i = 5;//it get's 5 only after visiting f()
    return local_i;
}
于 2009-08-06T14:48:46.927 回答
0

我认为这就是我在使用 g++ 4.7 和 CMake 时发生的情况(不确定这是否是有关 CMake 的相关细节)。我有一个在工厂注册功能的代码。它依赖于从全局初始化变量调用的构造函数。

当这段代码在静态链接库中时,初始化没有发生!它现在工作正常,当我将它移动到直接链接的目标文件时(即,它们没有首先组合到库中)。

所以,我怀疑你是对的。

于 2013-09-16T18:31:46.753 回答