Dynamic Memory Management

a garbage collector (the alternative C lacks)

/ GAR-bij /

In C, you free every block by hand, and the bugs in this whole field — leaks, dangling pointers, double-frees — come from getting that by-hand step wrong. Many other languages remove the chore entirely: you allocate memory and simply stop using it, and the language reclaims it for you automatically. The component that does this is a garbage collector. Understanding it is useful precisely because C does not have one, which is why C asks so much care of you.

The core idea: a garbage collector periodically figures out which heap objects your program can still reach and reclaims all the ones it cannot. The classic method is mark-and-sweep. Starting from the roots — the pointers your program can directly see, in local variables, globals, and registers — the collector follows every pointer, marking each object it can reach as live. Anything it never reaches is garbage: your program has no way to refer to it anymore, so it is safe to reclaim. The collector then sweeps up all the unmarked objects, returning their memory to be reused. Because reachability is computed automatically, you never call free, and the entire category of leak-by-forgotten-free and dangling-pointer bugs largely disappears (though you can still leak in a GC language by keeping references you no longer need). Languages built on this idea include Java, Go, Python, JavaScript, and C-sharp.

It is a real trade-off, not a free lunch — which is exactly why systems languages often avoid it. A collector costs CPU time to trace the heap, uses extra memory, and traditionally introduces pauses while it runs, which can be unacceptable for code that must respond on a tight deadline. That is part of why C, and Rust, deliberately do without a garbage collector and give you precise control over when memory is released. Rust is the interesting middle path: it has no garbage collector, yet its compiler tracks ownership and lifetimes to insert the frees automatically and prove at compile time that there are no dangling pointers or double-frees — the safety of GC for these bugs, without the runtime collector, paid for instead with rules you satisfy while writing the code.

Mark-and-sweep, in plain steps: 1. Start from the roots (locals, globals, registers). 2. Follow every pointer, MARK each object you can reach as live. 3. SWEEP: reclaim every object that was never marked. C has no step like this — you must call free() yourself.

A collector reclaims unreachable objects automatically; C leaves that entirely to you, which is the source of this field's bugs.

A garbage collector ends manual free but is not free of cost — it spends CPU and memory and can pause the program. It also does not prevent logic-level leaks (keeping references you no longer need) or deadlocks.

Also called
GCautomatic memory management垃圾回收自動記憶體管理