Advanced Memory Management
Master memory management in C — understand heap internals, prevent memory leaks, debug memory errors, and write memory-safe code.
Memory Layout & Allocation
A C program's memory is organized into segments: Text (compiled code, read-only), Data (initialized global/static variables), BSS (uninitialized global/static, zero-filled), Heap (dynamic allocation via malloc/calloc/realloc, grows upward), and Stack (local variables, function calls, grows downward). malloc(size) allocates size bytes on the heap and returns a void pointer (you must cast it). calloc(count, size) allocates count × size bytes and initializes to zero — use for arrays. realloc(ptr, new_size) resizes an existing allocation — may move the data to a new location if needed. free(ptr) deallocates memory — sets it as available but doesn't zero it (dangling pointer if you use ptr after free). Critical rules: always check malloc return value (can return NULL on failure), always free what you malloc (memory leaks), never free twice (double-free corruption), never use after free (undefined behavior), and always free in the reverse order of allocation.
Common Memory Errors
- Memory Leak: Allocating memory without freeing it — accumulates over time, eventually exhausting system memory. Use Valgrind to detect: valgrind --leak-check=full ./program
- Buffer Overflow: Writing beyond allocated bounds — overwrites adjacent memory, causes crashes or security vulnerabilities. The #1 source of security bugs in C
- Use-After-Free: Accessing memory after calling free() — data may be overwritten by another allocation. Set pointers to NULL after free to crash early instead
- Double Free: Calling free() on the same pointer twice — corrupts heap metadata, causes crashes or exploitable vulnerabilities. Track allocation/deallocation carefully
- Uninitialized Memory: Reading variables before setting them — contains garbage values. Local variables are NOT zero-initialized in C (unlike global/static). Use calloc or memset
- Stack Overflow: Too-deep recursion or very large local arrays — use heap allocation (malloc) for large buffers instead of stack arrays
Memory Debugging Tools
- Valgrind: Gold standard for memory debugging — detects leaks, uninitialized reads, buffer overflows, use-after-free. Runs program in a virtual machine (20-50x slower but thorough)
- AddressSanitizer (ASan): Compiler flag -fsanitize=address — detects buffer overflows, use-after-free, double-free at compile time with 2x slowdown. Much faster than Valgrind
- MemorySanitizer (MSan): Detects reads of uninitialized memory — compile with -fsanitize=memory. Catches subtle bugs that produce non-deterministic behavior
- GDB with watchpoints: Set watchpoints on memory addresses — break when the value at that address changes. Debug corruption by finding exactly which line modifies memory
- Custom Memory Allocator: Wrap malloc/free with tracking — log every allocation with file:line, detect leaks at program exit by checking unfreed entries