何时初始化静态和全局变量?

时间:2021-02-05 16:46:27

In C++ I know static and global objects are constructed before the main function. But as you know, in C, there is no such kind initialization procedure before main.

在C ++中,我知道静态和全局对象是在main函数之前构造的。但是如你所知,在C中,main之前没有这种类型的初始化过程。

For example, in my code:

例如,在我的代码中:

int global_int1 = 5;int global_int2;static int static_int1 = 4;static int static_int2;
  • When are these four variables initialized?
  • 这四个变量何时初始化?

  • Where values for initialization like 5 and 4 are stored during compilation? How to manage them when initialization?
  • 在编译期间存储初始值如5和4的位置?初始化时如何管理它们?


EDIT:
Clarification of 2nd question.

编辑:澄清第二个问题。

  • In my code I use 5 to initialize global_int1, so how can the compiler assign 5 to global_int? For example, maybe the compiler first store the 5 value at somewhere (i.e. a table), and get this value when initialization begins.
  • 在我的代码中,我使用5来初始化global_int1,那么编译器如何为global_int分配5?例如,编译器可能首先将5值存储在某处(即表),并在初始化开始时获取该值。

  • As to "How to manage them when initialization?", it is realy vague and I myself does not how to interpret yet. Sometimes, it is not easy to explain a question. Overlook it since I have not mastered the question fully yet.
  • 至于“如何在初始化时管理它们?”,它真的很模糊,我自己也不知道如何解释。有时,解释一个问题并不容易。忽略它,因为我还没有完全掌握这个问题。

4 个解决方案

#1


21  

By static and global objects, I presume you mean objects withstatic lifetime defined at namespace scope. When such objectsare defined with local scope, the rules are slightly different.

通过静态和全局对象,我假设您指的是在命名空间范围内定义的具有静态生命周期的对象。当使用本地范围定义此类对象时,规则略有不同。

Formally, C++ initializes such variables in three phases:1. Zero initialization2. Static initialization3. Dynamic initializationThe language also distinguishes between variables which requiredynamic initialization, and those which require staticinitialization: all static objects (objects with staticlifetime) are first zero initialized, then objects with staticinitialization are initialized, and then dynamic initializationoccurs.

形式上,C ++在三个阶段初始化这些变量:1。零初始化2。静态初始化3。动态初始化语言还区分了需要动态初始化的变量和需要静态初始化的变量:所有静态对象(具有staticlifetime的对象)首先进行零初始化,然后初始化具有静态初始化的对象,然后动态初始化。

As a simple first approximation, dynamic initialization meansthat some code must be executed; typically, staticinitialization doesn't. Thus:

作为简单的第一近似,动态初始化意味着必须执行某些代码;通常,静态初始化不会。从而:

extern int f();int g1 = 42;    //  static initializationint g2 = f();   //  dynamic initialization

Another approximization would be that static initialization iswhat C supports (for variables with static lifetime), dynamiceverything else.

另一个近似是静态初始化是C支持(对于具有静态生命周期的变量),动态其他。

How the compiler does this depends, of course, on theinitialization, but on disk based systems, where the executableis loaded into memory from disk, the values for staticinitialization are part of the image on disk, and loadeddirectly by the system from the disk. On a classical Unixsystem, global variables would be divided into three "segments":

编译器如何执行此操作当然取决于初始化,但在基于磁盘的系统上,可执行文件从磁盘加载到内存中,staticinitialization的值是磁盘上映像的一部分,并由系统直接从磁盘加载。在传统的Unix系统中,全局变量将分为三个“段”:

text:
The code, loaded into a write protected area. Staticvariables with `const` types would also be placed here.
data:
Static variables with static initializers.
bss:
Static variables with no-initializer (C and C++) or with dynamicinitialization (C++). The executable contains no image for thissegment, and the system simply sets it all to `0` beforestarting your code.

I suspect that a lot of modern systems still use somethingsimilar.

我怀疑很多现代系统仍然使用类似的东西。

EDIT:

One additional remark: the above refers to C++03. For existingprograms, C++11 probably doesn't change anything, but it doesadd constexpr (which means that some user defined functionscan still be static initialization) and thread local variables,which opens up a whole new can of worms.

还有一句话:上面提到的是C ++ 03。对于现有程序,C ++ 11可能不会改变任何东西,但它确实添加了constexpr(这意味着一些用户定义的函数仍然可以是静态初始化)和线程局部变量,这开辟了一整套新的蠕虫。

#2


12  

Preface: The word "static" has a vast number of different meanings in C++. Don't get confused.

前言:“静态”一词在C ++中有很多不同的含义。不要混淆。

All your objects have static storage duration. That is because they are neither automatic nor dynamic. (Nor thread-local, though thread-local is a bit like static.)

所有对象都有静态存储持续时间。那是因为它们既不是自动的也不是动态的。 (也不是线程局部的,虽然线程局部有点像静态。)

In C++, Static objects are initialized in two phases: static initialization, and dynamic initialization.

在C ++中,静态对象初始化为两个阶段:静态初始化和动态初始化。

  • Dynamic initialization requires actual code to execute, so this happens for objects that start with a constructor call, or where the initializer is an expression that can only be evaluated at runtime.

    动态初始化需要执行实际代码,因此对于以构造函数调用开头的对象,或者初始化程序是只能在运行时进行求值的表达式。

  • Static initialization is when the initializer is known statically and no constructor needs to run. (Static initialization is either zero-initialization or constant-initialization.) This is the case for your int variables with constant initializer, and you are guaranteed that those are indeed initialized in the static phase.

    静态初始化是指静态地知道初始化程序并且不需要运行构造函数。 (静态初始化是零初始化或常量初始化。)对于具有常量初始化程序的int变量,情况就是如此,并且保证这些变量在静态阶段确实已初始化。

  • (Static-storage variables with dynamic initialization are also zero-initialzed statically before anything else happens.)

    (在发生任何其他情况之前,具有动态初始化的静态存储变量也会静态地进行零初始化。)

The crucial point is that the static initialization phase doens't "run" at all. The data is there right from the start. That means that there is no "ordering" or any other such dynamic property that concerns static initialization. The initial values are hard-coded into your program binary, if you will.

关键的一点是,静态初始化阶段根本不会“运行”。数据从一开始就存在。这意味着没有“排序”或任何其他涉及静态初始化的动态属性。如果愿意,初始值将硬编码到程序二进制文件中。

#3


3  

When are these four variables initialized?

这四个变量何时初始化?

As you say, this happens before program startup, i.e. before main begins. C does not specify it further; in C++, these happen during the static initialisation phase before objects with more complicated constructors or initialisers.

正如你所说,这发生在程序启动之前,即在main开始之前。 C没有进一步说明;在C ++中,这些在静态初始化阶段发生在具有更复杂的构造函数或初始化器的对象之前。

Where values for initialization like 5 and 4 are stored during compilation?

在编译期间存储初始值如5和4的位置?

Typically, the non-zero values are stored in a data segment in the program file, while the zero values are in a bss segment which just reserves enough memory for the variables. When the program starts, the data segment is loaded into memory and the bss segment is set to zero. (Of course, the language standard doesn't specify this, so a compiler could do something else, like generate code to initialise each variables before running main).

通常,非零值存储在程序文件中的数据段中,而零值位于bss段中,该bss段仅为变量保留足够的存储器。程序启动时,数据段被加载到内存中,bss段被设置为零。 (当然,语言标准没有指定这一点,因此编译器可以执行其他操作,例如生成代码以在运行main之前初始化每个变量)。

#4


1  

Paraphrased from the standard:

从标准转述:

All variables which do not have dynamic storage duration, do not have thread local storage duration, and are not local, have static storage duration. In other words, all globals have static storage duration.

所有没有动态存储持续时间的变量,没有线程本地存储持续时间,并且不是本地的,具有静态存储持续时间。换句话说,所有全局变量都具有静态存储持续时间。

Static objects with dynamic initialization are not necessarily created before the first statement in the main function. It is implementation defined as to whether these objects are created before the first statement in main, or before the first use of any function or variable defined in the same translation unit as the static variable to be initialized.

具有动态初始化的静态对象不一定在main函数中的第一个语句之前创建。它的实现定义是在main中的第一个语句之前,还是在第一次使用与要初始化的静态变量相同的转换单元中定义的任何函数或变量之前创建这些对象。

So, in your code, global_int1 and static_int1 are definitely initialized before the first statement in main because they are statically initialized. However, global_int2 and static_int2 are dynamically initialized, so their initialization is implementation defined according to the rule I mentioned above.

因此,在您的代码中,global_int1和static_int1肯定在main中的第一个语句之前初始化,因为它们是静态初始化的。但是,global_int2和static_int2是动态初始化的,因此它们的初始化是根据我上面提到的规则定义的实现。

As for your second point, I'm not sure I understand what you mean. Could you clarify?

至于你的第二点,我不确定我明白你的意思。你能澄清一下吗?

#1


21  

By static and global objects, I presume you mean objects withstatic lifetime defined at namespace scope. When such objectsare defined with local scope, the rules are slightly different.

通过静态和全局对象,我假设您指的是在命名空间范围内定义的具有静态生命周期的对象。当使用本地范围定义此类对象时,规则略有不同。

Formally, C++ initializes such variables in three phases:1. Zero initialization2. Static initialization3. Dynamic initializationThe language also distinguishes between variables which requiredynamic initialization, and those which require staticinitialization: all static objects (objects with staticlifetime) are first zero initialized, then objects with staticinitialization are initialized, and then dynamic initializationoccurs.

形式上,C ++在三个阶段初始化这些变量:1。零初始化2。静态初始化3。动态初始化语言还区分了需要动态初始化的变量和需要静态初始化的变量:所有静态对象(具有staticlifetime的对象)首先进行零初始化,然后初始化具有静态初始化的对象,然后动态初始化。

As a simple first approximation, dynamic initialization meansthat some code must be executed; typically, staticinitialization doesn't. Thus:

作为简单的第一近似,动态初始化意味着必须执行某些代码;通常,静态初始化不会。从而:

extern int f();int g1 = 42;    //  static initializationint g2 = f();   //  dynamic initialization

Another approximization would be that static initialization iswhat C supports (for variables with static lifetime), dynamiceverything else.

另一个近似是静态初始化是C支持(对于具有静态生命周期的变量),动态其他。

How the compiler does this depends, of course, on theinitialization, but on disk based systems, where the executableis loaded into memory from disk, the values for staticinitialization are part of the image on disk, and loadeddirectly by the system from the disk. On a classical Unixsystem, global variables would be divided into three "segments":

编译器如何执行此操作当然取决于初始化,但在基于磁盘的系统上,可执行文件从磁盘加载到内存中,staticinitialization的值是磁盘上映像的一部分,并由系统直接从磁盘加载。在传统的Unix系统中,全局变量将分为三个“段”:

text:
The code, loaded into a write protected area. Staticvariables with `const` types would also be placed here.
data:
Static variables with static initializers.
bss:
Static variables with no-initializer (C and C++) or with dynamicinitialization (C++). The executable contains no image for thissegment, and the system simply sets it all to `0` beforestarting your code.

I suspect that a lot of modern systems still use somethingsimilar.

我怀疑很多现代系统仍然使用类似的东西。

EDIT:

One additional remark: the above refers to C++03. For existingprograms, C++11 probably doesn't change anything, but it doesadd constexpr (which means that some user defined functionscan still be static initialization) and thread local variables,which opens up a whole new can of worms.

还有一句话:上面提到的是C ++ 03。对于现有程序,C ++ 11可能不会改变任何东西,但它确实添加了constexpr(这意味着一些用户定义的函数仍然可以是静态初始化)和线程局部变量,这开辟了一整套新的蠕虫。

#2


12  

Preface: The word "static" has a vast number of different meanings in C++. Don't get confused.

前言:“静态”一词在C ++中有很多不同的含义。不要混淆。

All your objects have static storage duration. That is because they are neither automatic nor dynamic. (Nor thread-local, though thread-local is a bit like static.)

所有对象都有静态存储持续时间。那是因为它们既不是自动的也不是动态的。 (也不是线程局部的,虽然线程局部有点像静态。)

In C++, Static objects are initialized in two phases: static initialization, and dynamic initialization.

在C ++中,静态对象初始化为两个阶段:静态初始化和动态初始化。

  • Dynamic initialization requires actual code to execute, so this happens for objects that start with a constructor call, or where the initializer is an expression that can only be evaluated at runtime.

    动态初始化需要执行实际代码,因此对于以构造函数调用开头的对象,或者初始化程序是只能在运行时进行求值的表达式。

  • Static initialization is when the initializer is known statically and no constructor needs to run. (Static initialization is either zero-initialization or constant-initialization.) This is the case for your int variables with constant initializer, and you are guaranteed that those are indeed initialized in the static phase.

    静态初始化是指静态地知道初始化程序并且不需要运行构造函数。 (静态初始化是零初始化或常量初始化。)对于具有常量初始化程序的int变量,情况就是如此,并且保证这些变量在静态阶段确实已初始化。

  • (Static-storage variables with dynamic initialization are also zero-initialzed statically before anything else happens.)

    (在发生任何其他情况之前,具有动态初始化的静态存储变量也会静态地进行零初始化。)

The crucial point is that the static initialization phase doens't "run" at all. The data is there right from the start. That means that there is no "ordering" or any other such dynamic property that concerns static initialization. The initial values are hard-coded into your program binary, if you will.

关键的一点是,静态初始化阶段根本不会“运行”。数据从一开始就存在。这意味着没有“排序”或任何其他涉及静态初始化的动态属性。如果愿意,初始值将硬编码到程序二进制文件中。

#3


3  

When are these four variables initialized?

这四个变量何时初始化?

As you say, this happens before program startup, i.e. before main begins. C does not specify it further; in C++, these happen during the static initialisation phase before objects with more complicated constructors or initialisers.

正如你所说,这发生在程序启动之前,即在main开始之前。 C没有进一步说明;在C ++中,这些在静态初始化阶段发生在具有更复杂的构造函数或初始化器的对象之前。

Where values for initialization like 5 and 4 are stored during compilation?

在编译期间存储初始值如5和4的位置?

Typically, the non-zero values are stored in a data segment in the program file, while the zero values are in a bss segment which just reserves enough memory for the variables. When the program starts, the data segment is loaded into memory and the bss segment is set to zero. (Of course, the language standard doesn't specify this, so a compiler could do something else, like generate code to initialise each variables before running main).

通常,非零值存储在程序文件中的数据段中,而零值位于bss段中,该bss段仅为变量保留足够的存储器。程序启动时,数据段被加载到内存中,bss段被设置为零。 (当然,语言标准没有指定这一点,因此编译器可以执行其他操作,例如生成代码以在运行main之前初始化每个变量)。

#4


1  

Paraphrased from the standard:

从标准转述:

All variables which do not have dynamic storage duration, do not have thread local storage duration, and are not local, have static storage duration. In other words, all globals have static storage duration.

所有没有动态存储持续时间的变量,没有线程本地存储持续时间,并且不是本地的,具有静态存储持续时间。换句话说,所有全局变量都具有静态存储持续时间。

Static objects with dynamic initialization are not necessarily created before the first statement in the main function. It is implementation defined as to whether these objects are created before the first statement in main, or before the first use of any function or variable defined in the same translation unit as the static variable to be initialized.

具有动态初始化的静态对象不一定在main函数中的第一个语句之前创建。它的实现定义是在main中的第一个语句之前,还是在第一次使用与要初始化的静态变量相同的转换单元中定义的任何函数或变量之前创建这些对象。

So, in your code, global_int1 and static_int1 are definitely initialized before the first statement in main because they are statically initialized. However, global_int2 and static_int2 are dynamically initialized, so their initialization is implementation defined according to the rule I mentioned above.

因此,在您的代码中,global_int1和static_int1肯定在main中的第一个语句之前初始化,因为它们是静态初始化的。但是,global_int2和static_int2是动态初始化的,因此它们的初始化是根据我上面提到的规则定义的实现。

As for your second point, I'm not sure I understand what you mean. Could you clarify?

至于你的第二点,我不确定我明白你的意思。你能澄清一下吗?