pointers-memory · intermediate · ~15 min
Save-next-before-free pattern — the universal linked-structure destroy idiom.
Free every node of a singly-linked list without reading any node after it has been freed. The naïve loop reads head->next after free(head) — a use-after-free; the fix is to save the next pointer first.
The list node type is:
typedef struct node { int v; struct node *next; } node_t;
The broken version (do NOT do this):
while (head) { free(head); head = head->next; } // reads freed memory next iteration
Implement void destroy(node_t *head) that frees every node in the list, capturing each node's next pointer before freeing the node. No main — the grader builds the list and calls it.
head — the first node of the list, or NULL for an empty list.
No return value. Every node is freed, with no use-after-free.
list 1 -> 2 -> 3 -> 4, destroy(head) -> all four nodes freed
destroy(NULL) -> no-op
next before each free. Must run cleanly under AddressSanitizer.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.
head — the first node, or NULL.
No return value; every node is freed.
No allocations. Save next before free. Must run cleanly under ASan.
typedef struct node { int v; struct node *next; } node_t;
void destroy(node_t *head) { /* TODO */ }
Reading head->next after free(head) — use-after-free.
NULL head (no-op); single-node list.
O(n).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.