Skip to main content
๐Ÿ“œ WAYPOINT LESSON

Ownership Contracts

โญโญโญ advancedโณ 15 min read๐Ÿ“ Lesson 168 of 225

Who owns what: create/destroy pairs, transfer of ownership, borrows, and liveness counters as executable documentation.

Every pointer has an owner

For every heap allocation the codebase must answer: which function or struct is responsible for freeing this, and when? Everything else holds a borrow โ€” a pointer valid only within the owner's lifetime.

The API shapes that encode ownership

  • handle_create / handle_destroy โ€” the module owns; callers hold a borrow between the two calls.
  • take(buf) โ€” the callee takes ownership: after the call, the caller must not free or use buf.
  • give() โ€” the callee returns ownership: the caller must eventually free it.
  • const T *view(const T *x) โ€” pure borrow: never freed by the receiver.

APIs that hide which shape they use are bugs in documentation form.

Liveness counters make contracts executable

A module-level objects_alive counter โ€” incremented in create, decremented in destroy โ€” turns 'the caller leaked' from a code-review opinion into a testable fact. Production code does this in debug builds; this course does it in every ownership challenge.

โšก Now practice

Ready to Code
Ownership Contract DrillsCreate/destroy discipline, transfer semantics, cleanup ladders, and refcounting โ€” each observable through liveness counters.
4 challenges ยท ยท ~24 min