Skip to main content

Ownership and the Classic Errors

beginner14 min readLesson 48 of 148

Leak, double free, use-after-free โ€” recognizing all three on sight.

Ownership in one line

Every allocation has exactly one owner โ€” a function or module responsible for freeing it. When you take ownership, you take the duty. When you hand it over, you give up the right to free it yourself. Design functions so the ownership story is obvious from the name:

  • create_* / alloc_* โ†’ caller frees
  • *_destroy / *_free โ†’ this function frees; don't double-free afterwards

Leak

void f(void) {
    int *p = malloc(8 * sizeof(int));
    if (cond) return;          // LEAK: p dies unfreed
    free(p);
}

Memory leaks rarely crash a program โ€” they starve it slowly. Long-running programs (servers!) die from accumulated leaks.

Double free

free(p);
free(p);        // undefined behavior โ€” heap metadata corrupted

Set p = NULL after freeing; free(NULL) is defined and harmless.

Use-after-free

free(p);
*p = 5;         // undefined behavior โ€” the block may already be reused

This is the most dangerous of the three: it can silently "work" in tests and corrupt data in production.

Reading them in the wild

None of these crash at the error site. The skill is recognizing the SHAPE: a return/break path that skips free, two frees of one name, any use of a name after its free. Training that eye is what the practice below is for.

Now practice

Ownership DisciplineNULL-checked allocation helpers and a cleanup function that frees exactly what it created.3 challenges ยท ยท ~16 min