If you write p[-1], you overwrite the header. The allocator gets confused and crashes later.
Garbage Collection (GC): “The Cleaning Crew”
Languages like Java or Python use GC. C does not, but understanding GC is crucial because it’s effectively what you must simulate in your head.
GC is based on Reachability.
Imagine memory as a graph of nodes (objects) connected by arrows (pointers).
Roots are the entry points: Registers, Stack Variables, Global Variables.
The Algorithm: Mark and Sweep
Stop the World: Pause the program.
Mark: Start at the Roots. Follow every arrow. Mark every node you visit as “Live”.
Sweep: Walk through the entire heap. If a node is not marked, nobody can reach it. It is garbage. Reclaim it.
Fragmentation: The Warehouse Problem
Why can malloc fail even if we have free memory?
External Fragmentation:
Imagine you have 100 bytes of free space, but it’s split into two chunks of 50 bytes separated by a used block.
If you ask for 80 bytes, malloc fails.
Total Free: 100.
Max Contiguous: 50.
Internal Fragmentation:
You ask for 5 bytes. The allocator works in blocks of 16 bytes. It gives you 16.
11 bytes are wasted inside the block.
Practice: Debugging Memory
Scenario 1: The Leak
Loop running 1,000 times, allocating 1KB, never freeing.
Result: RAM usage climbs steadily until the OS kills the process (OOM Killer).
Fix: Every malloc needs a matching free in every code path.
Scenario 2: Double Free
free(p);free(p);
The first free marks the block as “Available”. The second free sees an “Available” block and corrupts the free-list details. This often leads to security exploits.
Fix: Set p = NULL; after freeing. free(NULL) is safe (does nothing).
Scenario 3: Use-After-Free
free(p);printf("%d", *p);
The memory at p might now belong to someone else! You are reading corrupted data or crashing.