简体   繁体   English

C ++中函数内的静态变量 - 即使函数没有运行也会分配?

[英]Static variables within functions in C++ - allocated even if function doesn't run?

I've been reading up on C++ on the Internet, and here's one thing that I haven't been quite able to find an answer to. 我一直在网上阅读C ++,这是我无法找到答案的一件事。

I know that static variables used within functions are akin to globals, and that subsequent invocations of that function will have the static variable retain its value between calls. 我知道函数中使用的静态变量类似于全局变量,并且该函数的后续调用将使静态变量在调用之间保持其值。

However, if the function is never called, does the static variable get allocated? 但是,如果从未调用该函数,静态变量是否会被分配?

Thanks 谢谢

If the function is never called, it is likely that your linker will deadstrip both the function and the static variable, preventing it from entering .rodata , .data , or .bss segments (or your executable file format's equivalents). 如果函数没有被调用,很可能是你的连接将deadstrip两者的功能和静态变量,防止其进入.rodata.data ,或.bss段(或你的可执行文件格式的当量)。

However, there are various reasons why a linker might not deadstrip (flags telling it not to, an inability to determine what depends on the symbol, etc). 但是,有多种原因导致链接器可能没有死区(标志告诉它不能,无法确定取决于符号的内容等)。

It's worth checking your linker map file (sometimes just a text file!), or using objdump , nm , or dumpbin utilities on the final executable to see if the symbol or related symbols (such as static initializer code) survived. 值得检查链接器映射文件(有时只是文本文件!),或者在最终可执行文件上使用objdumpnmdumpbin实用程序来查看符号或相关符号(例如静态初始化代码)是否存活。

The C++ Standard, section 6.7 says: C ++标准,第6.7节说:

The zero-initialization (8.5) of all local objects with static storage duration (3.7.1) is performed before any other initialization takes place. 具有静态存储持续时间(3.7.1)的所有本地对象的零初始化(8.5)在任何其他初始化发生之前执行。 A local object of POD type (3.9) with static storage duration initialized with constant-expressions is initialized before its block is first entered. 具有使用常量表达式初始化的静态存储持续时间的POD类型(3.9)的本地对象在其首次输入块之前被初始化。 An implementation is permitted to per- form early initialization of other local objects with static storage duration under the same conditions that an implementation is permitted to statically initialize an object with static storage duration in namespace scope (3.6.2). 允许实现在允许实现静态初始化具有命名空间范围内的静态存储持续时间的对象的相同条件下,以静态存储持续时间执行其他本地对象的早期初始化(3.6.2)。 Otherwise such an object is initialized the first time control passes through its declaration; 否则,在第一次控制通过其声明时初始化这样的对象; such an object is considered initialized upon the completion of its initialization. 这样的对象在初始化完成时被认为是初始化的。

Which indicates that local static objects are normally initialised the first time the control flow encounters them. 这表示本地静态对象通常在控制流第一次遇到它们时初始化。 However, they may well be allocated before this - the standard is somewhat reticent on what static storage actually is, except with reference to static object lifetimes. 但是,它们可能在此之前被分配 - 除了参考静态对象生存期之外,标准对静态存储实际上有些保持沉默。

Every object in C++ has two nested time-periods associated with it: storage duration and lifetime . C ++中的每个对象都有两个与之关联的嵌套时间段: 存储持续时间生命周期 Storage duration is the period for which the raw memory occupied by the object is allocated. 存储持续时间是分配对象占用的原始内存的时间段。 Lifetime is the period between construction and destruction of an actual object in that memory. 生命周期是构造和破坏该存储器中的实际对象之间的时间段。 (For objects of POD-types construction-destruction either doesn't matter or not applicable, so their lifetime matches their storage duration). (对于POD类型构造的对象 - 破坏要么无关紧要要么不适用,所以它们的寿命与它们的存储持续时间相匹配)。

When someone says "allocated" they usually refer to storage duration . 当有人说“已分配”时,他们通常会提到存储时间 The language doesn't actually specify exactly when the object's storage duration begins. 该语言实际上并未准确指定对象的存储持续时间何时开始。 It is sufficient to require that shall begin at some point before the object's lifetime begins. 要求在对象的生命周期开始之前的某个时刻开始就足够了。

For this reason, in general case a static object defined inside a function might never begin its lifetime and, theoretically, it's storage duration does not have to begin either. 因此,在一般情况下,函数内定义的静态对象可能永远不会从其生命周期开始,理论上,它的存储持续时间也不必开始。 So, in theory, in might not even get "allocated". 因此,理论上,甚至可能没有“分配”。

In practice though, all objects with static storage duration ("globals", local statics, etc.) are normally treated equally: they are assigned a specific amount of storage early, at the program's startup. 但实际上,具有静态存储持续时间(“全局”,局部静态等)的所有对象通常都是平等对待的:在程序启动时,它们会在早期分配特定的存储量。


As an additional note, if a local object with static storage duration requires a non-trivial initialization, this initialization is carried out when the control passes over the definition for the very first time. 另外需要注意的是,如果具有静态存储持续时间的本地对象需要进行非平凡的初始化,则在控件第一次通过定义时执行此初始化。 So in this example 所以在这个例子中

void foo() {
  static int *p = new int[100];
}

the dynamic array will never be allocated if the function is never called. 如果永远不调用该函数,则永远不会分配动态数组。 And it will be allocated only once if the function is called. 如果调用该函数,它将只被分配一次。 This doesn't look like what you are asking about, but I mention this just in case. 这看起来不像你要问的,但我提到这是为了以防万一。

Im sure that thats going to be up to the implementation. 我确信这将取决于实施。 What MSVC does is - static objects are allocated in the automatic data segment of the EXE or DLL. MSVC的作用是 - 在EXE或DLL的自动数据段中分配静态对象。 However, the constructor is only executed the first time the function containing the static is executed. 但是,构造函数仅在第一次执行包含静态的函数时执行。

Yes, actual allocation is compiler dependent, although I think that every compiler just reserves the space in the .static segment of the executable (or the equivalent in its executable file format). 是的,实际分配是依赖于编译器的,虽然我认为每个编译器只保留可执行文件的.static段中的空间(或其可执行文件格式中的等价物)。
The initialization, however takes place only the firs time that the execution flow encounters the static object, and that is required by the standard. 然而,初始化仅发生执行流遇到静态对象的第一次,并且是标准所要求的。
Beware that initialization of global static objects works in a different way, though. 但请注意, 全局静态对象的初始化以不同的方式工作。 You can get very good answers to almost every question at the C++ FAQ lite site. 您可以在C ++ FAQ lite网站上获得几乎所有问题的非常好的答案。 I am also fond of Scott Meyers's "Effective C++". 我也喜欢Scott Meyers的“Effective C ++”。

Depends. 要看。 If you mean, never called, as in, the function is literally never invoked, then your compiler will probably not allocate it, or even put in the function code. 如果你的意思是,永远不会调用,因为函数实际上从未被调用过,那么你的编译器可能不会分配它,甚至不会放入函数代码。 If, however, you made it dependent on, say, user input, and that user input just happened to never come up, then it will probably be pre-allocated. 但是,如果你让它依赖于用户输入,并且用户输入恰好从未出现过,那么它可能会被预先分配。 However, you're treading in a minefield here, and it's best just to assume that it is always created by the time control enters the function(s) that refer to it. 但是,你正在这里的雷区中进行攻击,最好只是假设它始终由时间控件进入引用它的函数创建。

Static variables defined on classes (members) or functions are not allocated dynamically on stack during function call, like non static ones. 在函数调用期间,在类(成员)或函数上定义的静态变量不会在堆栈上动态分配,就像非静态变量一样。 They are allocated in another area of generated code reserved for global and static data. 它们被分配在为全局和静态数据保留的生成代码的另一个区域中。 So, if you call the function or not, instantiate classes that contain static members or not, a space to their data will be reserved on program data area anyway. 因此,如果您是否调用该函数,实例化包含静态成员的类,则无论如何都会在程序数据区保留其数据空间。

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

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