views:

279

answers:

7

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.

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

+1  A: 

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. However, the constructor is only executed the first time the function containing the static is executed.

Chris Becke
+8  A: 

The C++ Standard, section 6.7 says:

The zero-initialization (8.5) of all local objects with static storage duration (3.7.1) is performed before any other initialization takes place. A local object of POD type (3.9) with static storage duration initialized with constant-expressions is initialized before its block is first entered. 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). 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.

anon
A: 

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).
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. I am also fond of Scott Meyers's "Effective C++".

garph0
+13  A: 

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).

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.

leander
+1 For mentioning deadstrip and the possibility that the linker will remove the variable(s) along with the function.
Thomas Matthews
*note: .rodata, .data, and .bss are unix-specific. (but +1)
Billy ONeal
@Billy ONeal: System V ABI, yes? I wonder what the history of these segments is... I assumed they were built into ELF, but you can (and we do) specify custom segments all the time, and the ELF format doesn't seem to have much special treatment for the common ones (other than setting various `SHT_*` flags etc differently). Anyone have a reference for the equivalent windows sections? (Maybe somewhere in the PE/COFF documentation? Time to go digging...)
leander
Most of the names for Windows seem to be close to the same -- `.data`, `.rdata`, `.text` -- there's mention of a `bss` section in various bits of documentation, but it seems like the recent MS linkers merge this into `.data`.
leander
A: 

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.

DeadMG
+3  A: 

Every object in C++ has two nested time-periods associated with it: storage duration and lifetime. 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).

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.

AndreyT
This seems to be true (p will not be initialized until the function's first call). This is kind of weird: what happens if the function foo is called from an arbitrary thread? Let's say we have 100 threads that at some point need to call foo... Which thread will initialize p? It will be a race condition. Anyway, it is a bad practice to use such static objects as it is very hard/awkward to un-initialize them.
botismarius
A: 

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.

Jorg B Jorge