ProblemsMemory ManagementThe observer that must not own
ExpertMemory Management

The observer that must not own

Context

A cache holds pointers to sessions, but must not keep dead sessions alive — that is exactly what weak references are for. The object dies when the last strong reference goes; the control block dies later, when the last weak reference goes. Mix the two lifetimes up and you get either a leak or a double free.

Task

A SharedPtr with a control block is already written. Implement WeakPtr: it observes the object without owning it. expired() says whether the object is gone; lock() returns a real SharedPtr (empty if the object died). The control block must live while at least one WeakPtr remains — and be freed with the last reference of either kind.

Constraints

  • WeakPtr(const SharedPtr&), copy constructor and destructor work
  • expired() is true exactly when no strong references remain
  • lock() returns an owning SharedPtr, or an empty one if expired
  • The object is destroyed by the LAST strong reference; the control block — by the last reference of any kind
  • No leaks and no double frees (the grader runs ASan)

Before you code

  • Why does WeakPtr need the control block after the object is already destroyed?
  • What goes wrong if the control block is freed while WeakPtrs remain?
  • Why must lock() increment the strong counter before returning?

Tests

  • #1lock() while the owner lives
  • #2expired() after the owner dies
  • #3lock() extends the object lifetime
  • #4Weak copies outlive the owner safely

Hints

Hint 1

Two counters, two lifetimes: strong == 0 kills the object; strong == 0 AND weak == 0 kills the control block. Update SharedPtr::release accordingly.

Hint 2

lock() is the only place that turns weak into strong: check expired(), bump the strong counter, hand the block to the private SharedPtr constructor.

Editorweak-ptr-expired.cpp
Results

Hit Submit (or ⌘/Ctrl + ↵) — test results will show up here.