为什么全局变量和静态变量被初始化为默认值?

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

In C/C++, why are globals and static variables initialized to default values?

在C/ c++中,为什么全局变量和静态变量被初始化为默认值?

Why not leave it with just garbage values? Are there any special reasons for this?

为什么不让它只保留垃圾值呢?有什么特别的原因吗?

5 个解决方案

#1


65  

  1. Security: leaving memory alone would leak information from other processes or the kernel.

    安全性:仅保留内存将泄漏来自其他进程或内核的信息。

  2. Efficiency: the values are useless until initialized to something, and it's more efficient to zero them in a block with unrolled loops. The OS can even zero freelist pages when the system is otherwise idle, rather than when some client or user is waiting for the program to start.

    效率:这些值在初始化到某个值之前都是无用的,在一个带有未滚动循环的块中将它们归零会更有效。当系统处于空闲状态时,操作系统甚至可以将空闲列表页面清空,而不是当某个客户机或用户等待程序启动时。

  3. Reproducibility: leaving the values alone would make program behavior non-repeatable, making bugs really hard to find.

    可重现性:只保留值将使程序行为不可重复,从而使查找错误变得非常困难。

  4. Elegance: it's cleaner if programs can start from 0 without having to clutter the code with default initializers.

    优雅性:如果程序可以从0开始,而不需要使用默认的初始化器使代码混乱,那么它就更简洁了。

One might then wonder why the auto storage class does start as garbage. The answer is two-fold:

有人可能想知道为什么自动存储类开始时是垃圾。答案是双重的:

  1. It doesn't, in a sense. The very first stack frame page at each level (i.e., every new page added to the stack) does receive zero values. The "garbage", or "uninitialized" values that subsequent function instances at the same stack level see are really the previous values left by other method instances of your own program and its library.

    从某种意义上说,它不是。每一层的第一个堆栈帧页面(例如。,添加到堆栈的每个新页面)会接收到零值。相同堆栈级别的后续函数实例看到的“垃圾”或“未初始化”值实际上是您自己的程序及其库的其他方法实例留下的以前的值。

  2. There might be a quadratic (or whatever) runtime performance penalty associated with initializing auto (function locals) to anything. A function might not use any or all of a large array, say, on any given call, and it could be invoked thousands or millions of times. The initialization of statics and globals, OTOH, only needs to happen once.

    可能存在与初始化auto(函数局部变量)相关的二次运行时性能损失。一个函数可能不会在任何给定的调用中使用任何或所有的大数组,它可以被调用数千或数百万次。静态和全局变量OTOH的初始化只需要发生一次。

#2


23  

Because with the proper cooperation of the OS, 0 initializing statics and globals can be implemented with no runtime overhead.

因为在操作系统的适当合作下,0初始化静态和全局变量可以在没有运行时开销的情况下实现。

#3


17  

Section 6.7.8 Initialization of C99 standard (n1256) answers this question:

第6.7.8节C99标准的初始化(n1256)回答了这个问题:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:

如果具有自动存储持续时间的对象没有显式初始化,则其值是不确定的。如果一个具有静态存储时间的对象没有显式地初始化,则:

— if it has pointer type, it is initialized to a null pointer;

-如果有指针类型,则初始化为空指针;

— if it has arithmetic type, it is initialized to (positive or unsigned) zero;

-如果具有算术类型,则初始化为(正的或无符号的)零;

— if it is an aggregate, every member is initialized (recursively) according to these rules;

-如果是聚合,则根据这些规则对每个成员进行初始化(递归地);

— if it is a union, the first named member is initialized (recursively) according to these rules.

-如果它是一个联合,第一个命名的成员将根据这些规则进行初始化(递归地)。

#4


6  

Think about it, in the static realm you can't tell always for sure something is indeed initialized, or that main has started. There's also a static init and a dynamic init phase, the static one first right after the dynamic one where order matters.

想一想,在静态领域中,您不能总是确定某些东西确实已经初始化,或者main已经启动。还有一个静态init和一个动态init阶段,静态初始阶段在动态初始阶段之后,顺序很重要。

If you didn't have zeroing out of statics then you would be completely unable to tell in this phase for sure if anything was initialized AT ALL and in short the C++ world would fly apart and basic things like singletons (or any sort of dynamic static init) would simple cease to work.

如果你没有归零的静力学,那么你完全无法肯定地告诉在这个阶段如果任何初始化,总之c++世界早就分崩离析了,基本的单例(或任何形式的动态静态init)将简单的停止工作。

The answer with the bulletpoints is enthusiastic but a bit silly. Those could all apply to nonstatic allocation but that isn't done (well, sometimes but not usually).

公告的答案是热情的,但有点傻。这些都可以应用于非静态分配,但这还没有完成(有时很好,但通常不是)。

#5


2  

In C, statically-allocated objects without an explicit initializer are initialized to zero (for arithmetic types) or a null pointer (for pointer types). Implementations of C typically represent zero values and null pointer values using a bit pattern consisting solely of zero-valued bits (though this is not required by the C standard). Hence, the bss section typically includes all uninitialized variables declared at file scope (i.e., outside of any function) as well as uninitialized local variables declared with the static keyword.

在C中,没有显式初始化器的静态分配对象被初始化为零(对于算术类型)或空指针(对于指针类型)。C的实现通常表示零值和空指针值,使用的是仅由零值位组成的位模式(尽管这不是C标准所要求的)。因此,bss部分通常包含在文件范围中声明的所有未初始化的变量(例如。,除了未初始化的局部变量外,还使用static关键字声明。

Source: Wikipedia

资料来源:*

#1


65  

  1. Security: leaving memory alone would leak information from other processes or the kernel.

    安全性:仅保留内存将泄漏来自其他进程或内核的信息。

  2. Efficiency: the values are useless until initialized to something, and it's more efficient to zero them in a block with unrolled loops. The OS can even zero freelist pages when the system is otherwise idle, rather than when some client or user is waiting for the program to start.

    效率:这些值在初始化到某个值之前都是无用的,在一个带有未滚动循环的块中将它们归零会更有效。当系统处于空闲状态时,操作系统甚至可以将空闲列表页面清空,而不是当某个客户机或用户等待程序启动时。

  3. Reproducibility: leaving the values alone would make program behavior non-repeatable, making bugs really hard to find.

    可重现性:只保留值将使程序行为不可重复,从而使查找错误变得非常困难。

  4. Elegance: it's cleaner if programs can start from 0 without having to clutter the code with default initializers.

    优雅性:如果程序可以从0开始,而不需要使用默认的初始化器使代码混乱,那么它就更简洁了。

One might then wonder why the auto storage class does start as garbage. The answer is two-fold:

有人可能想知道为什么自动存储类开始时是垃圾。答案是双重的:

  1. It doesn't, in a sense. The very first stack frame page at each level (i.e., every new page added to the stack) does receive zero values. The "garbage", or "uninitialized" values that subsequent function instances at the same stack level see are really the previous values left by other method instances of your own program and its library.

    从某种意义上说,它不是。每一层的第一个堆栈帧页面(例如。,添加到堆栈的每个新页面)会接收到零值。相同堆栈级别的后续函数实例看到的“垃圾”或“未初始化”值实际上是您自己的程序及其库的其他方法实例留下的以前的值。

  2. There might be a quadratic (or whatever) runtime performance penalty associated with initializing auto (function locals) to anything. A function might not use any or all of a large array, say, on any given call, and it could be invoked thousands or millions of times. The initialization of statics and globals, OTOH, only needs to happen once.

    可能存在与初始化auto(函数局部变量)相关的二次运行时性能损失。一个函数可能不会在任何给定的调用中使用任何或所有的大数组,它可以被调用数千或数百万次。静态和全局变量OTOH的初始化只需要发生一次。

#2


23  

Because with the proper cooperation of the OS, 0 initializing statics and globals can be implemented with no runtime overhead.

因为在操作系统的适当合作下,0初始化静态和全局变量可以在没有运行时开销的情况下实现。

#3


17  

Section 6.7.8 Initialization of C99 standard (n1256) answers this question:

第6.7.8节C99标准的初始化(n1256)回答了这个问题:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:

如果具有自动存储持续时间的对象没有显式初始化,则其值是不确定的。如果一个具有静态存储时间的对象没有显式地初始化,则:

— if it has pointer type, it is initialized to a null pointer;

-如果有指针类型,则初始化为空指针;

— if it has arithmetic type, it is initialized to (positive or unsigned) zero;

-如果具有算术类型,则初始化为(正的或无符号的)零;

— if it is an aggregate, every member is initialized (recursively) according to these rules;

-如果是聚合,则根据这些规则对每个成员进行初始化(递归地);

— if it is a union, the first named member is initialized (recursively) according to these rules.

-如果它是一个联合,第一个命名的成员将根据这些规则进行初始化(递归地)。

#4


6  

Think about it, in the static realm you can't tell always for sure something is indeed initialized, or that main has started. There's also a static init and a dynamic init phase, the static one first right after the dynamic one where order matters.

想一想,在静态领域中,您不能总是确定某些东西确实已经初始化,或者main已经启动。还有一个静态init和一个动态init阶段,静态初始阶段在动态初始阶段之后,顺序很重要。

If you didn't have zeroing out of statics then you would be completely unable to tell in this phase for sure if anything was initialized AT ALL and in short the C++ world would fly apart and basic things like singletons (or any sort of dynamic static init) would simple cease to work.

如果你没有归零的静力学,那么你完全无法肯定地告诉在这个阶段如果任何初始化,总之c++世界早就分崩离析了,基本的单例(或任何形式的动态静态init)将简单的停止工作。

The answer with the bulletpoints is enthusiastic but a bit silly. Those could all apply to nonstatic allocation but that isn't done (well, sometimes but not usually).

公告的答案是热情的,但有点傻。这些都可以应用于非静态分配,但这还没有完成(有时很好,但通常不是)。

#5


2  

In C, statically-allocated objects without an explicit initializer are initialized to zero (for arithmetic types) or a null pointer (for pointer types). Implementations of C typically represent zero values and null pointer values using a bit pattern consisting solely of zero-valued bits (though this is not required by the C standard). Hence, the bss section typically includes all uninitialized variables declared at file scope (i.e., outside of any function) as well as uninitialized local variables declared with the static keyword.

在C中,没有显式初始化器的静态分配对象被初始化为零(对于算术类型)或空指针(对于指针类型)。C的实现通常表示零值和空指针值,使用的是仅由零值位组成的位模式(尽管这不是C标准所要求的)。因此,bss部分通常包含在文件范围中声明的所有未初始化的变量(例如。,除了未初始化的局部变量外,还使用static关键字声明。

Source: Wikipedia

资料来源:*