Mark and Sweep GC
Mark-and-sweep takes a completely different approach from reference counting: instead of tracking counts continuously, it periodically pauses the program and asks one question directly, "starting from everything currently reachable, what's still alive?" Anything left over gets swept away.
It runs in two phases:
- Mark: starting from a set of "roots" (global variables, local variables currently on the stack), recursively visit every object reachable from them, flagging each one as
marked. - Sweep: walk every object the allocator has ever handed out, free any that weren't marked, then clear the marks for next time.
Notice markObject checks obj->marked before recursing, this is exactly what solves the cycle problem from the last lesson: two objects referencing each other both simply get marked once each, then correctly swept together if nothing external points to either.
The tradeoff
| Refcounting | Mark and Sweep | |
|---|---|---|
| Handles cycles | No | Yes |
| Overhead | A little, on every assignment | A pause during collection |
| Simplicity | Simpler per-operation | More bookkeeping (roots, linked list of all objects) |
Neither is strictly "better", refcounting is used where memory needs to be freed the instant it's unreachable (like Swift's ARC), mark-and-sweep is used where occasional pauses are acceptable in exchange for never leaking cycles (like most JavaScript engines).
Final project
Combine everything from this course: write a small C program with an Obj type (int and string, like the earlier lessons), a way to track "roots", and a working mark + sweep pair that correctly frees unreached objects, including a deliberate reference cycle to prove it doesn't leak. Submit a link to your repository below, an instructor will review it before you can mark this lesson complete.