⬅ Previous Next ➡

Storage & Memory Concepts

Storage & Memory Concepts in C
  • Storage classes define a variable's scope (where it is visible), lifetime (how long it exists), and storage location.
  • Memory layout explains how a C program is stored in RAM (code, globals, heap, stack).
  • Stack is used for function calls/local variables, while Heap is used for dynamic memory allocation.
  • Improper use of dynamic memory can cause memory leaks.

1) Storage Classes in C

  • auto: default for local variables (inside functions).
  • register: suggests storing variable in CPU register (faster access, address cannot be taken).
  • static:
    • Inside function: retains value between calls (lifetime = whole program).
    • Outside function: makes global variable/function file-scope (not accessible from other files).
  • extern: declares a global variable defined in another file.
#include <stdio.h>

void counter() {
    static int c = 0; // retains value
    c++;
    printf("Count = %d\n", c);
}

int main() {
    counter(); // 1
    counter(); // 2
    counter(); // 3
    return 0;
}

2) Memory Layout of a C Program

  • Text/Code Segment: compiled instructions (read-only).
  • Data Segment:
    • Initialized Data: global/static with initial values.
    • Uninitialized Data (BSS): global/static without initialization (set to 0).
  • Heap: dynamic memory allocation (malloc/calloc/realloc/free).
  • Stack: function call frames, local variables, return addresses.
// Quick view (conceptual)
// [ Text / Code ]
// [ Data (init)  ]
// [ BSS (uninit) ]
// [ Heap  ....   ]  grows upward
// [ Stack ....   ]  grows downward

3) Stack vs Heap Memory

  • Stack:
    • Automatic memory (created/removed automatically).
    • Stores local variables and function call information.
    • Faster but limited size.
  • Heap:
    • Manual memory management using malloc/free.
    • Used for dynamic arrays/structures.
    • Larger than stack but slower than stack.
#include <stdio.h>
#include <stdlib.h>

int main() {
    int x = 10; // stack (local variable)

    int *arr = (int*)malloc(5 * sizeof(int)); // heap
    if (arr == NULL) {
        printf("Memory allocation failed!\n");
        return 0;
    }

    for (int i = 0; i < 5; i++) {
        arr[i] = (i + 1) * 10;
    }

    printf("Stack x = %d\n", x);
    printf("Heap arr[0] = %d\n", arr[0]);

    free(arr); // important!
    return 0;
}

4) Memory Leaks

  • Memory leak happens when allocated heap memory is not freed.
  • Leak effect: program memory usage keeps increasing and can crash.
  • Fix: always use free() for malloc/calloc/realloc allocations.
#include <stdio.h>
#include <stdlib.h>

int main() {
    int *p = (int*)malloc(sizeof(int));

    if (p == NULL) return 0;

    *p = 100;
    printf("%d\n", *p);

    // free(p);  // If you forget this line => memory leak
    // Better:
    free(p);
    p = NULL;

    return 0;
}

5) Basic Debugging Concepts

  • Compile with warnings: use -Wall -Wextra to catch common mistakes.
  • Use printf debugging: print variables and flow to locate issues.
  • Check pointers: NULL checks before use.
  • Common runtime errors:
    • Segmentation fault (invalid memory access)
    • Stack overflow (deep recursion)
    • Buffer overflow (writing beyond array size)
// Helpful compile commands (GCC)
// gcc program.c -o program -Wall -Wextra
// gcc program.c -o program -g          (debug symbols for debugger)

6) Quick Notes

  • auto = default local, static = retains value, extern = defined elsewhere.
  • Stack is automatic, heap is manual.
  • Always free() dynamically allocated memory to avoid leaks.
  • Use compiler warnings and debug flags to find issues faster.
⬅ Previous Next ➡