Exposition
A program can be seen as a text file. This text file is nothing but a series of instructions that say things like we need this thing, we need to store it here, when event a happens, we need to then cause event b to happen, and so on. From a computer view, everything becomes a series of binary. How does this happen though? The transition from a text file into an executable? This page is a light refresher on the memory layouts of programs.
Core Ideas
When a program is loaded into memory, the OS will allocate a logical block of space. We say logical because in reality that block may or may not be fragmented.
This is done via an abstraction called virtual address space. The program will arrange itself assuming a starting point of 0x0 or some baseline and number its references accordingly. The program then talks to the CPU which then talks to the Memory Managment Unit (MMU) that will actually look up the correct location for the reference. The OS maintains Page Table (book) and it is read by the MMU.
The MMU has its own cache the TLB (Translation Lookaside Buffer) which lists the last 64 to 1024 translations as a nice speedup.
Stacks
Conventionally, stacks start at the top (higher numbered memory addresses) and grow downwards.
Heaps
Heaps start at the bottom (lower numbered memory addresses) and grow up. A heap of trash climbs up. A stack of bricks falls down.
Stack and Heap Interaction
The stack starts at the higher address (right side) and grows down (left). The heap starts at the lower address (left side) and grows up (right). You might ask if they will ever touch. Yes but long before that the program will be terminated by the OS due to system limit and guard pages around the stack being violated.
Code
The compiled instructions of your program resider in this text segment area of the allocated memory block. It’s read-only and can not change.
Data Segements
Variables reside here; static and global. Typically you have variables you have initalized and those you have yet to. In either case, you have delcared for them and thus space must be allocated.
Heap
This is the dynamic memory allocation. The amount of data your program will use at runtime is never known.
Stack
The stack is used for function calls and local variables. For every function call, a stack frame is added to the stack.
Ordering
| Segment | Relative Address | Direction of Growth |
|---|---|---|
| Kernel Space | Highest (e.g., 0xFFFFFFFF) | Fixed |
| Stack | High | Downwards ↓ |
| (The Gap) | Mid-High | — |
| Heap | Mid-Low | Upwards ↑ |
| Data (.bss & .data) | Low | Fixed |
| Text (Code) | Lowest (e.g., 0x00000000) | Fixed |
Example Implementations
C++
Automatic variables are on the stack and vanish at function end. Dynamic variables declared by new are placed on the heap. Memory management is on you as there is no garbage collector.
Java
The stack will only hold primitives and references. Everything else is on the heap. JVM Garbage Collector manages said heap.
Go
Go will determine if a variables goes on the stack or the heap. There is a garbage collector and the compiler through ‘escape analysis’ optimizes layout for you.
Python
Stack stores frame for every function calls. The frames only contain references. Everything is on the heap. Memory management is done by reference counting and when nothing on the stack references the object on the heap. It is deleted.
Example Walkthroughs
C++
#include <iostream>
int main() {
const char* message = "Hello, World!"; // String literal
std::cout << message << std::endl;
return 0;
}
note that the function std::count is part of the standard library. The CPU jumps from the text segment of the program to the library’s memory space. The standard function is loaded into the “gap” of the allocated memory.
Python
# python_hello.py
message = "Hello World"
print(message)
The string itself is a PyObject. Every object contains the data itself and meta data, namely the reference count and a pointer to the type. Python doesnt use the hardware stack instead; it provides its own stack. Every frame itself is a PyObject and the garbage collector is of the highest order.