Skip to main content
Engineering LibreTexts

3.4: Memory segments

  • Page ID
    40721
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    The data of a running process is organized into five segments:

    • The code segment contains the program text; that is, the machine language instructions that make up the program.
    • The static segment contains immutable values, like string literals. For example, if your program contains the string "Hello, World", those characters will be stored in the static segment.
    • The global segment contains global variables and local variables that are declared static.
    • The heap segment contains chunks of memory allocated at run time, most often by calling the C library function malloc.
    • The stack segment contains the call stack, which is a sequence of stack frames. Each time a function is called, a stack frame is allocated to contain the parameters and local variables of the function. When the function completes, its stack frame is removed from the stack.

    The arrangement of these segments is determined partly by the compiler and partly by the operating system. The details vary from one system to another, but in the most common arrangement:

    • The text segment is near the “bottom” of memory, that is, at addresses near 0.
    • The static segment is often just above the text segment, that is, at higher addresses.
    • The global segment is often just above the static segment.
    • The heap is often above the global segment. As it expands, it grows up toward larger addresses.
    • The stack is near the top of memory; that is, near the highest addresses in the virtual address space. As the stack expands, it grows down toward smaller addresses.

    To determine the layout of these segments on your system, try running this program, which is in aspace.c in the repository for this book (see Section 0.2).

    #include <stdio.h>
    #include <stdlib.h>
    
    int global;
    
    int main ()
    {
        int local = 5;
        void *p = malloc(128);
        char *s = "Hello, World";
    
        printf ("Address of main is %p\n", main);
        printf ("Address of global is %p\n", &global);
        printf ("Address of local is %p\n", &local);
        printf ("p points to %p\n", p);
        printf ("s points to %p\n", s);
    }
    

    main is the name of a function; when it is used as a variable, it refers to the address of the first machine language instruction in main, which we expect to be in the text segment.

    global is a global variable, so we expect it to be in the global segment. local is a local variable, so we expect it to be on the stack.

    s refers to a “string literal", which is a string that appears as part of the program (as opposed to a string that is read from a file, input by a user, etc.). We expect the location of the string to be in the static segment (as opposed to the pointer, s, which is a local variable).

    p contains an address returned by malloc, which allocates space in the heap. “malloc” stands for “memory allocate.”

    The format sequence %p tells printf to format each address as a “pointer”, so it displays the results in hexadecimal.

    When I run this program, the output looks like this (I added spaces to make it easier to read):

    Address of main is   0x      40057d
    Address of global is 0x      60104c
    Address of local is  0x7ffe6085443c
    p points to          0x     16c3010
    s points to          0x      4006a4
    
    

    As expected, the address of main is the lowest, followed by the location of the string literal. The location of global is next, then the address p points to. The address of local is much bigger.

    The largest address has 12 hexadecimal digits. Each hex digit corresponds to 4 bits, so it is a 48-bit address. That suggests that the usable part of the virtual address space is \( 2^{48} \) bytes.

    As an exercise, run this program on your computer and compare your results to mine. Add a second call to malloc and check whether the heap on your system grows up (toward larger addresses). Add a function that prints the address of a local variable, and check whether the stack grows down.


    This page titled 3.4: Memory segments is shared under a CC BY-NC license and was authored, remixed, and/or curated by Allen B. Downey (Green Tea Press) .

    • Was this article helpful?