skip to content

Memory Management

Where values live and who reclaims them: stack versus heap, allocator design, tracing collection, reference counting and compile-time ownership. Interviewers probe where memory bugs begin.

part ofComputer science fundamentalsoverview, primer and where to startread it →
on this pageshow

explore

questions

131 · 6 sections

When you print the memory map of a running process, which regions does it contain and what does each hold?

level: juniorimportance: must knowfreq 76%
basics
~20 s

A process maps several regions with different rules: read-only code and constants, initialized static data, zero-filled static data, one growable heap, one stack per thread, and per-thread thread-local storage. Placement decides lifetime and who may write.

open as a page

What does one frame on a thread's call stack hold, and why does returning from the call release it for free?

level: juniorimportance: must knowfreq 72%
basics
~20 s

A call frame holds that call's return address, saved registers, local variables and spilled temporaries, plus space for outgoing arguments. Returning moves the stack pointer back past the whole frame, so release is one instruction with no bookkeeping.

open as a page

Why does storing through a pointer to a literal string constant fault, while storing into a heap block succeeds?

level: middleimportance: must knowfreq 58%
basics
~20 s

A literal lives in the read-only constants region, mapped without write permission, so the hardware refuses the store. A heap block sits in a writable mapping, so the identical instruction succeeds. The region's permissions decide, not the pointer.

open as a page

How do you estimate how deep a recursive call chain can go before it exhausts a thread's stack?

level: middleimportance: must knowfreq 58%
basics
~20 s

Divide the thread's stack size by the average frame size: a 1 MiB stack with 80-byte frames allows roughly 13,000 nested calls. Frame size is the lever - adding a 256-byte local buffer per frame cuts that to about 3,100.

open as a page

Before a compiler may place a new object on the stack instead of the heap, what must it prove?

level: middleimportance: must knowfreq 68%
basics
~20 s

That no reference to the object can be followed once the creating frame returns: it is never stored in longer-lived memory, returned, or published to another thread. Without that proof the object must go on the heap.

open as a page

In a per-request scratch arena reset at the response boundary, how do allocation and release actually work?

level: middleimportance: must knowfreq 62%
basics
~20 s

Allocation aligns one cursor, hands back its old position and advances it past the object, storing no per-object metadata. Nothing is released individually: at the response boundary the cursor is rewound to the start, which releases everything in the region at once.

open as a page

Which fragmentation does an allocator harness measure when it reports 100 MB requested but 128 MB occupied, and which does it miss?

level: middleimportance: must knowfreq 62%
basics
~10 s

That 28 MB gap is internal fragmentation: bytes lost rounding each request up to a whole block. It cannot see external fragmentation, the free-but-scattered space between blocks, because nobody occupies those bytes.

open as a page

When an allocator frees a block, how do boundary tags let it merge with both neighbouring free blocks in constant time?

level: middleimportance: must knowfreq 58%
basics
~20 s

Boundary tags repeat each block's size and free flag in a header and a footer, so a released block reaches both address neighbours by arithmetic and merges with whichever are free — no list scan.

open as a page

A heap allocator searching one free list can take the first block that fits or the smallest; what does each policy cost?

level: middleimportance: must knowfreq 66%
basics
~20 s

First fit stops at the first adequate block, so the search is short but early splits leave small remainders near the list head. Best fit scans the whole list for the tightest block, paying a full walk to leave a smaller remainder.

open as a page

How does a per-thread allocator cache make the common allocation path run with no synchronization at all?

level: middleimportance: must knowfreq 54%
basics
~20 s

A per-thread allocator cache gives each thread its own free list per size class. Allocation pops that private list's head, and since no other thread can reach it, the pop needs no lock — only refill and flush synchronize.

open as a page

A managed heap split into a young area and an older area rests on what observation about object lifetimes?

level: juniorimportance: must knowfreq 68%
basics
~20 s

Most objects die very young — the weak generational hypothesis. Splitting the heap by age lets a collector sweep the young area often and cheaply, where almost everything is already garbage, and touch the older area rarely.

open as a page

In a tracing garbage collector, what is a root, and why must a collection start from the root set?

level: juniorimportance: must knowfreq 68%
basics
~20 s

A root is a reference the collector can find without tracing anything first — a running thread's stack slot or register, a global table entry, a handle registered by code outside the collected heap. Everything the program can still touch starts at one of them.

open as a page

In three-colour marking (white unreached, grey reached but unscanned, black scanned), why may no black object reference a white one?

level: middleimportance: must knowfreq 58%
basics
~20 s

Black means already scanned, so the marker will not revisit it on its own. A reference from a black object to a white one is therefore a live object the trace never reaches — and would wrongly reclaim.

open as a page

When a collector splits one heap trace into many short increments, what does the running program experience instead of one long stop?

level: middleimportance: must knowfreq 62%
basics
~20 s

Many brief suspensions rather than one long one. The collector marks a bounded slice of the heap, hands control back, and resumes later from where it stopped. The longest pause shrinks; total collection work usually grows.

open as a page

Why does adding heap headroom above a service's live set make a tracing collector cheaper per allocated byte?

level: middleimportance: must knowfreq 58%
basics
~20 s

Tracing cost follows the live set, not the free space, while each cycle reclaims everything above the live set. Extra headroom therefore spreads the same tracing work over far more allocation before the next cycle is needed.

open as a page

In a proxy, every request thread copies and drops a handle to one shared read-only routing table. Why does that cost throughput?

level: middleimportance: must knowfreq 62%
basics
~10 s

Each copy and drop of a counted handle is an atomic read-modify-write of one shared count, so read-only sharing is still a write workload: cores must take exclusive turns owning that counter's cache line.

open as a page

Two objects in a counted heap hold references to each other and nothing outside can reach them; why is neither ever freed?

level: middleimportance: must knowfreq 66%
basics
~20 s

Each object's count is held above zero by the other, so no decrement ever reaches zero. A count records whether anything points at an object, not whether anything reachable does, so an unreachable ring keeps itself alive.

open as a page

In a reference-counted system, which events change an object's count, and what happens the moment that count reaches zero?

level: middleimportance: must knowfreq 62%
basics
~20 s

Every new owning handle to an object increments its count; every handle dropped or overwritten decrements it. At zero the object's cleanup runs, every handle it holds is released in turn, and its memory is reclaimed.

open as a page

In a reference-counted object graph, what happens to a weak handle when the last owning handle to its object is dropped?

level: middleimportance: must knowfreq 68%
basics
~20 s

It reads as absent from that moment on. Only owning handles are counted, so the last one dropping destroys the object immediately; weak handles are not counted, cannot delay that, and are never allowed to yield destroyed storage.

open as a page

A million-node counted chain loses its only head handle and every node is freed at once, so why can that hurt tail latency?

level: seniorimportance: must knowfreq 55%
basics
~20 s

One decrement can destroy a whole structure. The thread that dropped the head handle runs a million cleanups, decrements and frees inline, in the middle of whatever request it was serving, so a cheap-looking assignment becomes an unbounded pause.

open as a page

What is a borrow in an ownership discipline, and why can it never outlive the value's owner?

level: middleimportance: must knowfreq 66%
basics
~20 s

A borrow is temporary non-owning access to a value someone else must release. It carries no release duty, so it stays valid only while that owner still holds the value; outliving the owner leaves it naming storage already reclaimed.

open as a page

Why may many readers borrow the same value at once, while a writer must borrow it exclusively?

level: middleimportance: must knowfreq 58%
basics
~20 s

Readers all observe one unchanging value, so overlapping them changes nothing. A writer can resize, move or half-update it, so any other reference alive at that moment could read a torn or stale view. Exclusivity for writers is what rules that out.

open as a page

Why can a program built under a compile-time ownership discipline still leak heap memory with no unchecked code?

level: middleimportance: must knowfreq 58%
basics
~20 s

A leak is memory that is still owned and still reachable — a cache that never evicts, a registration nobody cancels. The checks prove every access is valid; they say nothing about how long an owner chooses to keep a block.

open as a page

Which memory-bug classes does a compile-time ownership discipline make unrepresentable rather than merely rarer?

level: middleimportance: must knowfreq 66%
basics
~20 s

Use-after-free, double free, and dangling references into a moved or resized container become unrepresentable: single ownership plus lifetime-checked borrows reject them before the program builds. Leaks and logic errors are untouched, because keeping memory reachable is safe.

open as a page

In a pipeline where one owning handle to a large chunk buffer carries the release duty, what does moving that handle do?

level: middleimportance: must knowfreq 66%
basics
~20 s

A move transfers the release duty to the destination handle and leaves the source owning nothing. The block stays at the same address; only the small owning record is copied, so the cost is the same for 4 KiB and 64 MiB.

open as a page

In a runtime that reclaims unreachable memory automatically, how can a program still leak memory?

level: juniorimportance: must knowfreq 74%
basics
~20 s

Automatic reclamation frees only what nothing can reach. A leak there is memory that stays reachable from something live - an unbounded cache, a growing registry, a collection nobody trims - but will never be used again.

open as a page

A container's memory ceiling kills a worker whose managed heap sits well under its configured maximum — why?

level: middleimportance: must knowfreq 62%
basics
~20 s

A container ceiling counts every byte the whole process holds; the configured maximum heap bounds only one region inside it. Thread stacks, runtime metadata, allocator caches and buffers living outside the managed heap are charged against the ceiling too.

open as a page

On a service's memory footprint chart, why is the post-collection floor the line you trend to decide whether it is leaking?

level: middleimportance: must knowfreq 72%
basics
~20 s

The post-collection floor is the live set: the bytes still reachable once the collector has finished. Peaks only record how much garbage piled up since the previous collection, so only a rising floor shows that memory is being retained.

open as a page

A gateway's footprint saw-tooths between 1.2 GB and 3.0 GB every forty seconds while every post-collection floor sits at 1.2 GB — what is going on?

level: middleimportance: must knowfreq 60%
basics
~20 s

That is churn, not a leak. The flat 1.2 GB floor says the live set is constant; the 1.8 GB reclaimed every forty seconds says the service allocates roughly 45 MB a second of short-lived objects. The fix is allocation rate, not a retainer hunt.

open as a page

In a heap snapshot, what does an object's retained size measure that its shallow size does not?

level: middleimportance: must knowfreq 66%
basics
~20 s

Shallow size is the bytes of the object itself: header, fields and its reference slots, but not their targets. Retained size adds everything that would become unreachable if that object did, so it measures what the object keeps alive.

open as a page