C programs in memory

To illustrate how a running C program is organized in memory, let's consider a sample C program and then depict its memory layout using an ASCII diagram. The memory of a running C program is typically divided into several segments:

  1. Code Section: Contains the compiled code (machine code) of the program.

  2. Data Section: Stores global and static variables that are initialized.

  3. BSS Section: Holds uninitialized global and static variables. The operating system sets all memory locations in this to zero before starting the program.

  4. Heap: Used for dynamic memory allocation.

  5. Stack: Stores local variables, function parameters, return addresses, etc.

Here's a sample C program that includes various types of variables and memory allocations:

#include <stdlib.h>

int globalVar = 5;          // Global variable
int globalVarUnInit         // Global variable - uninitialized
static int staticVar = 10;  // Static variable

void exampleFunction(int param) {
    static int staticLocal = 3;  // Static local variable
    int localVar = 4;            // Local variable
    char *dynamicVar = malloc(10 * sizeof(char));  // Dynamic memory allocation

    // ... rest of the function
}

int main() {
    const char *strLiteral = "Hello, World!";  // String literal
    exampleFunction(2);
    return 0;
}

Now, let's create an ASCII diagram to represent how this program would be laid out in memory:

+---------------------------------------+  // lower memory addresses
|    Code Section                       |
| - main                                |
| - exampleFunction                     |
+---------------------------------------+
|  Read-Only Data                       |
| - "Hello, World!" (String Literal)    |
+---------------------------------------+
|     Data Section                      |
| - globalVar                           |
| - staticVar                           |
+---------------------------------------+
|       BSS                             |
| - globalVarUnInit                     |
| - staticLocal                         |        
+---------------------------------------+
|       Heap                            |
| - memory that the address             |
|   in dynamicVar points to             | 
|   |                                   |  // heap grows towards higher memory
|   |                                   |  // addresses
|   \/                                  |
|                                       |
+---------------------------------------+
|       Stack                           |
|   /\                                  |
|   |                                   |  // stack grows towards lower memory
|   |                                   |  // addresses
| - param (exampleFunction)             |
| - dynamicVar (exampleFunction)        |
| - localVar (exampleFunction)          |
| - return address                      |
| - strLiteral (main)                   |
+---------------------------------------+  // higher memory addresses

Explanation:

  • Code Section: Contains the machine code for main and exampleFunction.

  • Read-Only Data Section: Includes the string literal "Hello, World!". This section is read-only to protect the literals from accidental modification.

  • Data Section: Stores globalVar and staticVar since they are initialized.

  • BSS Section: Holds and staticLocal and globalVar since they're uninitialized at the start.

  • Heap: Memory allocated using malloc.

  • Stack: For exampleFunction, the stack includes param, dynamicVar, localVar, and the return address to main. It also includes the strLiteral pointer in the main function.