Programming Fundamentals › Memory & Runtime
Reference Counting
Freeing an object when nothing refers to it anymore.
Also known as: reference counting, refcount, reference count
Reference counting is a memory-management strategy that keeps a count of how many references point to each object. When you create a reference, the count goes up; when one goes away, it goes down. When the count reaches zero, the object is freed immediately.
obj = new() refcount = 1
a = obj refcount = 2
b = obj refcount = 3
b = null refcount = 2
a = null refcount = 1
obj = null refcount = 0 → freed now
It’s used in Python, Swift (ARC), Objective-C, and Rust’s Rc/Arc. Its big advantage over a tracing garbage collector is determinism: an object is reclaimed the moment its last reference disappears, with no separate collection pass and no wait. For latency-sensitive systems and for resources like file handles, that immediacy is valuable.
The classic mistakes:
- Reference cycles leak. If A holds a reference to B and B holds one to A, neither count ever reaches zero, and both stay alive forever — even though nothing external can reach them. This is the weakness of pure reference counting, and the reason tracing collectors exist. Break cycles with weak references.
- Overhead on every assignment. Each pointer copy updates a counter, which for a shared object across threads means atomic operations and cache traffic. A hot loop copying references can spend real time on bookkeeping.
- Thread safety of the counter. A non-atomic refcount updated from multiple threads can corrupt and cause double-free. Shared counting needs atomics (Rust’s
Arcversus single-threadedRc). - Assuming it’s free of pauses. Refcounting has no big pause, but it can free a large tree recursively at the drop of the last reference, causing a surprise delay. Releasing a huge structure isn’t instant.
- Confusing it with garbage collection. They’re both automatic reclamation, but by different means: counting tracks liveness continuously; tracing collectors find unreachable objects in batches.
In practice, reference counting and tracing are often combined — a tracing collector to reclaim cycles, or refcounting with cycle detection. The design question is whether you need deterministic release (counting) or freedom from cycles and per-assignment overhead (tracing). It’s a middle point between manual management and a full GC.