Memory Management
Every running program uses memory to hold variables, objects, and data. How that memory is allocated and freed shapes performance, safety, and the bugs you face.
Stack vs Heap
The stack stores function call frames and small local variables. It grows and shrinks automatically as functions are called and return. It is fast, but limited in size.
The heap stores objects whose size or lifetime is not known up front. Allocations on the heap survive the function that created them and must eventually be released.
A pointer or reference is a small value stored on the stack that points at a larger object on the heap.
Manual vs Automatic Management
In C and C++, you allocate with new (or malloc) and must release with delete (or free). Forgetting causes a memory leak. Freeing twice or using freed memory causes a crash or security bug.
In Python, JavaScript, and Java, the runtime manages memory for you. You stop referencing an object and the runtime eventually reclaims it.
Reference Counting vs Garbage Collection
Reference counting (used by CPython) tracks how many references each object has. When the count drops to zero, the object is freed immediately. It is predictable but cannot handle cycles on its own.
Tracing garbage collection (used by the JVM and most JavaScript engines) periodically walks live references from known roots and collects whatever it cannot reach. It handles cycles, but introduces pauses and uses more memory.
Try It Yourself
- Write a function that allocates a 1000-element array, fills it, and releases it. Time the allocation in your language of choice.
- In C++, intentionally remove the
delete[]call and run a tool like Valgrind to see the leak. - Create two objects that reference each other, then drop both outside references, and reason about whether reference counting alone could free them.