pointers-memory · intermediate · ~15 min

Destroy a linked list without use-after-free

Save-next-before-free pattern — the universal linked-structure destroy idiom.

Challenge

Given a linked list typedef struct node { int v; struct node *next; } node_t;, implement void destroy(node_t *head) that frees every node in the list.

The naïve version is wrong:

while (head) { free(head); head = head->next; }   // UAF on the next iteration

Write the correct version that saves next before free.

Why this matters

The naïve destroy loop reads n->next AFTER free(n) — a textbook use-after-free. Doing it right is the single most-asked memory-safety question.

Input format

Head pointer (may be NULL).

Output format

All nodes freed.

Constraints

No allocations. Must run cleanly under ASan.

Starter code

typedef struct node { int v; struct node *next; } node_t;
void destroy(node_t *head) { /* TODO */ }

Common mistakes

Reading head->next after free(head) — use-after-free.

Edge cases to handle

NULL head (no-op); single-node list.

Complexity

O(n).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.