zhuang@linux:~/blog/process-memory-layout/$ cat

Process Memory Layout

$ grep tags process-memory-layout.md

The term process memory layout usually refers to the layout of a process’s virtual address space, not the direct layout of physical memory.

A typical layout looks roughly like this:

text
High addresses
┌─────────────────┐
│  Kernel space   │
├─────────────────┤
│      Stack      │  Local variables and function frames
│        ↓        │
│                 │
│        ↑        │
│       Heap      │  malloc / free
├─────────────────┤
│       BSS       │  Uninitialized global/static variables
│      Data       │  Initialized global/static variables
│      Text       │  Program code and read-only constants
└─────────────────┘
Low addresses

This is the virtual address view that the operating system gives to each process. When the CPU accesses a variable, it uses a virtual address. The memory management unit (MMU) translates that address into a physical address through page tables:

text
Virtual address → MMU / page table → physical memory page

Therefore:

  • Memory that is contiguous in virtual address space may not be contiguous in physical memory.
  • The relative positions of the stack and heap do not mean they have the same arrangement in physical memory.
  • Some virtual pages may not have physical memory assigned yet.
  • Some pages may be moved to swap space.
  • Shared libraries and shared memory can map different virtual addresses to the same physical page.
  • Native memory allocators such as malloc return virtual addresses; the operating system usually provides the underlying physical pages on demand.

The idea that “the stack grows downward and the heap grows upward” describes a common implementation, not a universal rule. The actual layout depends on the operating system, CPU architecture, linker, language runtime, and security features such as ASLR.

zhuang@linux:~/blog/process-memory-layout/$ comments