C/C++ Memory Layout

Each running program has its own memory layout, separated from other programs. The layout consists of a lot of segments, including:

  • stack: stores local variables
  • heap: dynamic memory for programmer to allocate
  • data: stores global variables, separated into initialized and uninitialized
  • text: stores the code being executed

In order to pinpoint each memory location in a program’s memory, we assign each byte of memory an “address”. The addresses go from 0 all the way to the largest possible address, depending on the machine. As the figure below, the textdata, and heap segments have low address numbers, while the stack memory has higher addresses.

Memory layout of a c++ program

By convention, we express these addresses in base 16 numbers. For instance, the smallest possible address is 0x00000000 (where the 0x means base 16), and the largest possible address could be 0xFFFFFFFF.

C Memory Layout C Code Example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// -------- GLOBAL VARIABLES --------
char value_global_init[] = "Global Init";   // Data segment
char value_global_uninit[15];              // BSS segment (uninitialized)

// Function declaration (Text segment)
void show_static_and_stack();

int main()
{
    // -------- HEAP VARIABLES --------
    char *value_heap_malloc;
    char *value_heap_calloc;
    char *value_heap_realloc;

    // Step 1: malloc
    value_heap_malloc = (char*)malloc(30 * sizeof(char));
    if (value_heap_malloc == NULL)
    {
        printf("Heap part - malloc: Allocation failed\n");
        return 1;
    }
    strcpy(value_heap_malloc, "Dynamically allocated string.");
    printf("Heap part - malloc: %s\n", value_heap_malloc);

    // Step 2: calloc
    value_heap_calloc = (char*)calloc(30, sizeof(char));
    if (value_heap_calloc == NULL)
    {
        printf("Heap part - calloc: Allocation failed\n");
        free(value_heap_malloc);
        return 1;
    }
    strcpy(value_heap_calloc, value_heap_malloc);
    printf("Heap part - calloc: %s\n", value_heap_calloc);

    // Step 3: realloc
    value_heap_realloc = (char*)realloc(value_heap_calloc, 60 * sizeof(char));
    if (value_heap_realloc == NULL)
    {
        printf("Heap part - realloc: Allocation failed\n");
        free(value_heap_calloc);
        free(value_heap_malloc);
        return 1;
    }
    strcat(value_heap_realloc, " With more reallocated content");
    printf("Heap part - realloc: %s\n", value_heap_realloc);

    // -------- GLOBAL VARIABLES OUTPUT --------
    strcpy(value_global_uninit, "Global Uninit");
    printf("Global part - Initialized: %s\n", value_global_init);
    printf("Global part - Uninitialized (BSS): %s\n", value_global_uninit);

    // -------- STATIC & STACK --------
    show_static_and_stack();

    // -------- TEXT PART --------
    printf("Text part: main() and show_static_and_stack() are in the Text segment.\n");

    // -------- CLEAN UP --------
    free(value_heap_malloc);
    free(value_heap_realloc);

    return 0;
}

void show_static_and_stack()
{
    // -------- STATIC --------
    static char value_static_init[] = "Static Init";   // Data segment
    static char value_static_uninit[15];               // BSS segment
    strcpy(value_static_uninit, "Static Uninit");

    // -------- STACK --------
    char value_stack[] = "Stack Var"; // Stack segment

    printf("Stack part: %s\n", value_stack);
    printf("Static part - Initialized (Data): %s\n", value_static_init);
    printf("Static part - Uninitialized (BSS): %s\n", value_static_uninit);
}

copy C Code & Paste it below the Compiler & Run

Memory Visualizer