简体   繁体   English

C ++全局初始化有多懒惰?

[英]How lazy can C++ global initialization be?

I'm used to thinking of all initialization of globals/static-class-members as happening before the first line of main(). 我习惯于考虑在main()的第一行之前发生的globals / static-class-members的所有初始化。 But I recently read somewhere that the standard allows initialization to happen later to "assist with dynamic loading of modules." 但我最近在某处读到,标准允许稍后进行初始化以“协助动态加载模块”。 I could see this being true when dynamic linking: I wouldn't expect a global initialized in a library to be initialized before I dlopen'ed the library. 在动态链接时我可以看到这是真的:在我开始使用库之前,我不希望在库中初始化全局初始化。 However, within a grouping of statically linked together translation units (my app's direct .o files) I would find this behavior very unintuitive. 但是,在一组静态链接在一起的翻译单元(我的应用程序的直接.o文件)中,我会发现这种行为非常不直观。 Does this only happen lazily when dynamically linking or can it happen at any time? 这只是在动态链接时懒得发生,还是随时都可以发生? (or was what I read just wrong? ;) (或者我读错了?;)

The standard has the following in 3.6.2/3: 该标准在3.6.2 / 3中有以下内容:

It is implementation-defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of namespace scope is done before the first statement of main. 它是实现定义的,无论命名空间作用域的对象的动态初始化(8.5,9.4,12.1,12.6.1)是否在main的第一个语句之前完成。 If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first use of any function or object defined in the same translation unit as the object to be initialized. 如果初始化延迟到main的第一个语句之后的某个时间点,则它应该在第一次使用与要初始化的对象相同的转换单元中定义的任何函数或对象之前发生。

But o Of course you can never officially tell when the initialization takes place since the initialization will occur before you access the variable! 但是o当然,您无法正式判断何时进行初始化, 因为在您访问变量之前将进行初始化! as follows: 如下:

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

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

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

I can conform that g++ 4.2.4 at least appears to perform the initialization of 'i2' before main. 我可以遵循g ++ 4.2.4至少似乎在main之前执行'i2'的初始化。

The problem that one wanted to solve with that rule is the one of dynamic loading. 人们想用该规则解决的问题是动态加载。 The allowance isn't restricted to dynamic loading and formally could happen for other cases. 津贴不仅限于动态载荷,其他情况也可能正式发生。 I don't know an implementation which use it for anything else than dynamic loading. 我不知道除了动态加载之外的其他任何实现。

Let's review a pseudocode: 让我们回顾一下伪代码:

In DLL: 在DLL中:

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

In application: 在申请中:

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

So according to static initializing AppVar2 gets 1+2=3 所以根据静态初始化,AppVar2获得1 + 2 = 3

Lazy initialization applicable for local static variables (regardless of DLL) 适用于本地静态变量的惰性初始化(不管DLL)

int f()
{
    static int local_i = 5;//it get's 5 only after visiting f()
    return local_i;
}

I think this is what happened in my case with g++ 4.7 and CMake (not sure if this is a relevant detail regarding CMake). 我认为这就是我使用g ++ 4.7和CMake的情况(不确定这是否是关于CMake的相关细节)。 I have a code that registers a function in the factory. 我有一个代码在工厂注册一个函数。 It relies on the constructor calling from a globally initialized variable. 它依赖于从全局初始化变量调用的构造函数。

When this code was in the statically linked library the initialization didn't happen! 当此代码在静态链接库中时 ,初始化没有发生! It is now working fine, when I moved it to the object files that linked directly (ie, they are not combined into a library first). 它现在工作正常,当我将它移动到直接链接的目标文件时(即,它们不首先组合到一个库中)。

So, I suspect that you are correct. 所以,我怀疑你是对的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM