catfood
catfood

Reputation: 355

When is static memory allocated in C/C++? At compile time or at the very beginning of when a program is run?

Different sources say different things for me - some StackOverflow answers say that it is allocated at compile time - others say it is "defined" at compile time, and allocated at the very beginning of runtime ("load time" is what some called it), while others say it is allocated at compile time. When is static memory exactly allocated in C/C++? (if it is to do with "defining" variables - can someone tell me what it means to "define" a variable on the memory level - that would be highly appreciated!)

Also, how would you during runtime set a pointer to the start of the allocated static memory?

Upvotes: 3

Views: 2091

Answers (3)

Eric Postpischil
Eric Postpischil

Reputation: 222322

In typical tools, memory with static storage duration is arranged in multiple steps:

  • The compiler generates data in object modules (likely passing through some form of assembly code) that describes needs for various kinds of memory: memory initialized to zero, memory initialized to particular values and is read-only thereafter, memory initialized to particular values and may be modified, memory that does not need to be initialized, and possibly others. The compiler also includes initial data as necessary, information about symbols that refer to various places in the required memory, and other information. At this point, the allocation of memory is in forms roughly like “8 bytes are needed in the constant data section, and a symbol called foo should be set to their address.”
  • The linker combines this information into similar information in an executable file. It also resolves some or all information about symbols. At this point, the allocation of memory is in forms like “The initialized non-constant data section requires 3048 bytes, and here is the initial data for it. When it is assigned a virtual address, the following symbols should be adjusted: bar is at offset 124 from the start of the section, baz is at offset 900…”
  • The program loader reads this information, allocates locations in the virtual address space for it, and may read some of the data from the executable file into memory or inform the operating system where the data is to be found when it is needed. At this point, the places in the code that refer to various symbols have been modified according to the final values of those symbols.
  • The operating system allocates physical memory for the virtual addresses. Often, this is done “on demand” in pieces (memory pages) when a process attempts to access the memory in a specific page, rather than being done at the time the program is initially loaded.

All-in-all, static memory is not allocated at any particular time. It is a combination of many activities. The effect on the program is largely that it occurs the same as if it were all allocated when the program started, but the physical memory might only be allocated just before an instruction actually executes. (The physical memory can even be taken away from the process and restored to it later.)

Upvotes: 10

The C standard says only this:

C11 5.1.2p1

[...]All objects with static storage duration shall be initialized (set to their initial values) before program startup. The manner and timing of such initialization are otherwise unspecified.

and

C11 6.2.4p2-3

2 The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

3 An object whose identifier is declared without the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.

But... this is further made complicated by the as-if rule, the actual implementation need to do this only as far as observable side effects go.

In fact in Linux for example, one could argue that the variables with static storage duration are initialized and allocated by the compiler and the linker when producing executable file. When the program is run, the dynamic linker (ld.so) then prepares the program segments so that the initialized data is memory-mapped (mmap) from the executable image to RAM, default (zero-initialized) data is mapped from zeroed pages.

While the virtual memory is allocated by the compiler, linker and dynamic linker, the actual writable RAM page frames are allocated only when you write to a variable on a page for the first time...

but you do not need to know about this in basic cases. It is as if the memory for variables with static storage duration were allocated and initialized just before main was entered, even though this is not actually the case.

Upvotes: 9

Joshua
Joshua

Reputation: 43188

Static memory is allocated in two steps.

Step 1 is carried out by the linker as it lays out the executable image and says where the static variables live in relative address space.

Step 2 is carried out by the loader when the process memory is actually allocated.

In C++, static objects are initialized before entering main. If you're not careful with your code you can see objects that are still zeros even though they have constructors that would always change that. (The compiler does as much constant evaluation as it can, so toy examples won't show it.)

Upvotes: 6

Related Questions