Skip to content
Go back

Memory Layouts

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

SegmentRelative AddressDirection of Growth
Kernel SpaceHighest (e.g., 0xFFFFFFFF)Fixed
StackHighDownwards ↓
(The Gap)Mid-High
HeapMid-LowUpwards ↑
Data (.bss & .data)LowFixed
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.


Share this post on:

Next Post
Multi-Platform Build