C/C++ Arena

Step 4 of 6

Free the whole list

Every node was allocated with malloc, so every node must be freed, or the list leaks. Freeing looks like a traversal, but with a trap:

for (struct Node *p = head; p != NULL; p = p->next) {
    free(p);     // then the loop reads p->next: use after free!
}

After free(p), the node's memory no longer belongs to you, so reading p->next to move on is undefined behavior. It may even appear to work, which is why this bug survives in real code. The fix: save the next pointer before freeing.

#include <stdio.h>
#include <stdlib.h>

struct Node {
    int value;
    struct Node *next;
};

int main(void) {
    struct Node *head = NULL;
    for (int i = 0; i < 4; i++) {
        struct Node *n = malloc(sizeof *n);
        if (!n) return 1;
        n->value = i;
        n->next = head;
        head = n;
    }
    int total = 0;
    while (head != NULL) {
        struct Node *next = head->next;
        total += head->value;
        free(head);
        head = next;
    }
    printf("freed all, total was %d\n", total);
    return 0;
}
freed all, total was 6

The loop reads what it needs from the node (its value and next) before freeing it, then moves on using the saved pointer. When the loop ends, head is NULL, which correctly describes an empty list.

This "save, free, advance" shape is how every linked structure is destroyed. Tools like AddressSanitizer report the wrong version immediately as a heap-use-after-free.

Your turn: write int free_list(struct Node *head) that frees every node and returns how many it freed.

Previous: Length and sum Next: Reverse a linked list