core21 min studyLesson 121 in Engineering

Object lifetimes: when an address stops being a resource

Separate allocation, object validity, pointer identity, and retention before deciding when a buffer may be reclaimed.

On this page

What you’ll understand

  • Draw a lifetime interval and test whether a proposed access fits inside it.
  • Explain why reusing the same numerical address does not validate a stale pointer.
  • Budget memory from overlapping retention intervals rather than allocation counts alone.

An address can remain unchanged after the object you meant to access has ceased to exist. This is why a dangling pointer is a question about a resource's history, not merely whether a machine address looks plausible. Build a timeline of allocation, initialization, access, and reclamation. Then ask which component proves that each access belongs to the intended live object.

An allocation timeline is necessary evidence

For this lesson, a buffer is allocated at time a, initialized before its first read, and released at time d. An ordinary access to its bytes must occur while the allocation remains live. A local variable containing an address may remain in scope after d, but its continued existence does not extend the buffer's lifetime. Stack storage can become invalid when a function returns; heap storage can become invalid when an owner releases it. Neither storage category permits arbitrary late access. Language rules can distinguish storage duration from the lifetime of a particular object placed there.

The interval test is deliberately incomplete. A pointer into a live allocation can still have the wrong alignment, insufficient accessible length, invalid provenance, an uninitialized value, or conflicting access permissions. A memory-mapped device may require additional rules. Treat lifetime as one required condition rather than a complete safety certificate. In a review, first identify the allocation's owner and release event, then check the access-specific obligations. This method exposes a missing lifetime argument without pretending to replace the target language's formal memory model.

taccess∈[a,d),a≤taccess<dt_{\rm access}\in[a,d),\qquad a\leq t_{\rm access}<d
a and d are allocation and release times in the same clock domain, with d later than a. This necessary condition assumes an ordinary allocation and excludes access at or after release; it does not establish initialization, bounds, provenance, or aliasing validity.↔ Scroll wide equations horizontally.

Reused addresses do not revive old objects

Imagine a decoder releasing a buffer and an allocator subsequently placing a different request's data at the same numerical address. A stale pointer can now appear to read reasonable bytes, creating a more confusing failure than an immediate crash. The new allocation has a different history and ownership contract. Reasoning solely from equal addresses misses that distinction. Safe interfaces therefore preserve an owning handle, borrow, or validated object identity rather than asking whether an old pointer still seems to work during a convenient test execution.

Invalidation can also occur during growth. A resizable container may obtain a new backing allocation and release the old one; a reference to an earlier element must not survive an operation that invalidates it. Whether a particular operation reallocates is an API question, and avoiding reallocation in one run is weaker than proving that the operation preserves references. Record the documented invalidation rules. When an asynchronous consumer retains a buffer, completion must include the consumer's final possible read, including cancellation and error paths, before reuse becomes justified.

M(t)=∑i=1Nsi 1[ai,di)(t)M(t)=\sum_{i=1}^{N}s_i\,\mathbf{1}_{[a_i,d_i)}(t)
s_i is the retained payload in bytes for allocation i, and the indicator is one while its interval contains time t. The sum counts distinct allocations once; shared views, allocator metadata, reserved capacity, and delayed operating-system release need separate accounting.↔ Scroll wide equations horizontally.

Retention and safety answer different questions

Keeping a buffer alive indefinitely can avoid one premature-release error while exhausting memory. Conversely, aggressively reusing buffers can reduce memory and introduce use-after-release. Establish an explicit lifecycle: acquisition, exclusive initialization, publication to readers, confirmation that readers have finished, and reclamation. For each transition, name the responsible component and the evidence it observes. A timeout often ends the caller's willingness to wait; it does not automatically prove a native worker or remote device has stopped accessing shared memory.

The queue lab illustrates retention pressure, not pointers. Interpret each waiting job as owning one equal-sized buffer. Press Reset, set arrival rate to four and service rate to two, then Play or Step; the fluid backlog begins at four and grows by two jobs per second. For a separate run, press Reset before setting arrival rate to two and service rate to four. Predict that the restored four-job backlog drains in two seconds, then Play or Step. Multiply the readout by an assumed buffer size to estimate waiting payload. The model omits executing jobs, allocator behavior, and all lifetime checks. Use that limitation to explain why a stable queue can still contain a dangling pointer, while a perfectly safe queue can still retain too much memory.

Count overlapping buffer lifetimes

Buffer A retains 4 MiB from time 0 through just before 8 seconds. Buffer B retains 6 MiB from time 3 through just before 10 seconds. A consumer proposes reading A at time 9.

  1. Between times 3 and 8 both distinct allocations are live, so their combined payload is 4 + 6 = 10 MiB. Before time 3 only A contributes.

  2. At time 9, A's interval has ended and B contributes 6 MiB. The proposed read of A fails the necessary lifetime test even if its old address remains mapped.

  3. Delay A's release until its final legitimate reader finishes, or arrange for that reader to own an independent copy. Recalculate the overlapping peak after choosing the lifecycle.

The result

The original peak is 10 MiB, and the read at 9 seconds is invalid under the stated schedule. Reducing a memory total does not prove that its remaining accesses are safe.

Explore the model

Interactive lab

Interactive lab · queue

Waiting work retains buffers

Press Reset, set λ=4 and μ=2, then Play or Step the fluid model max(0,4+(λ−μ)t). Predict two additional waiting buffers per second. For a separate experiment, press Reset, set λ=2 and μ=4, predict the restored four-job backlog drains in two seconds, then Play or Step. This shows waiting retention only; it neither represents pointers nor checks object lifetimes.

Waiting work retains buffersFluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Current readings: Fluid backlog: 4; Net rate · λ − μ: −1 /s; M/M/1 mean residence: 1 s. All parameters are adjustable with the labeled controls below.02.557.51001.534.56Elapsed time · sFluid backlogλ < μ
Fluid backlogCurrent time
Fluid backlog
4
Net rate · λ − μ
−1 /s
M/M/1 mean residence
1 s
t = 0 s

Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forMemory capacity and temporal safety need separate arguments even when each queued job owns a buffer.

Check your understanding

A freed allocation's address is immediately reused for another allocation. What validates an old pointer to the first object?

Try it yourself

Three distinct 2 MiB buffers have intervals [0,5), [2,7), and [4,6) seconds. Find the peak payload and the payload at time 6.

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Check intervals between consecutive endpoints, remembering that the release endpoint is excluded.

Compare with the solution

All three coexist from time 4 through just before 5, producing a 6 MiB peak. At time 6 the first and third intervals have ended, leaving 2 MiB from the second. This counts payload, not allocator reservation or memory still held by the operating system.

Take it with you

  • A stored address does not own or extend the referent's lifetime.
  • Reallocation and address reuse require reasoning about object history.
  • Calculate overlapping retention while independently proving access validity.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.