pointers-memory · intermediate · ~18 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.Transfer exercise: apply the lesson to a complete function contract.
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.
head is NULL or an owned finite acyclic heap-node list. Free every node exactly once; no aliases may be used afterward.
typedef struct node { int v; struct node *next; } node_t;
void destroy(node_t *head) { /* TODO */ }
Reading head->next after releasing head or leaking the final node.
Empty list; one node; multiple nodes; save each next link before freeing its node.
O(n).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.