There are different kinds of storage areas:
- Text: Contains the executable code (named here for completeness)
- Initialised data: Global and static variables
- Uninitialised data: Global and static variables (initialised to zero when the application starts)
- Stack: Local variables
- Heap: Allocated storage using
new()
or malloc()
Memory for the first two kinds is part of the executable itself and is allocated by the operating system when loading the application into memory.
The memory for unitialised global data is also allocated by the operating system and initialised to zero.
Stack memory is allocated by the operating system when a thread is started. For the main thread, the size is determined from the executable file. Other threads created during runtime will use the same size as default value but a different size can be passed as parameter to the thread creation function.
Each time a local variable is created, it will be assigned the address of the
stack pointer and that is decremented by the size of the variable (stacks are using the memory in top down direction). Once the stack pointer reaches the bottom, a stack overflow occurs and the application terminates because the stack memory is not resizable during runtime.
A compiler may also decide to store local variables in CPU registers instead of the stack. This can be also proposed with the
register
keyword.
Heap memory is allocated in chunks during runtime. This is done by code inserted by the compiler to every application (called
heap manager). When a request for memory can't be fulfilled from the current heap memory, the heap manager will request a larger block of memory from the operating system.
There is generally no difference between the memory allocation or assignemnt of basic and complex types (besides that the compiler might store basic types in registers rather than the stack).
Some examples:
int global1 = 1;
static int global2 = 2;
int global1U;
static int* globalPtr;
void some_func()
{
static int localS1 = 1;
static int localS2;
int local1;
int local2 = 2;
int localArr[10];
SomeObj obj;
register r = 0;
int *localPtr = new int[10];
SomeObj *objPtr = new SomeObj();
globalPtr = new int[10];
}