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

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

/*
 * free_all_nodes() is rewritten to enable tail recursion.
 * Compile with gcc -O2 to enable tail recursion optimization.
 *
 * Run it with a large numner of nodes (like one million) to see
 * non-optimized binary stack-overflowing whereas the tail-optimized
 * version runs with no problem.
 *
 * You can also see the disassembly with objdump -d to see 
 * the tail-optimized version do not have a recursive call.
 */
void free_all_nodes(struct Node *head) {
    if (head == NULL) {
        return;
    }
    struct Node *head_next = head->next;
    free(head);
    free_all_nodes(head_next);
}

int main(int argc, char **argv) {
    assert(argc == 2);
    int n = atoi(argv[1]);
    struct Node *head = NULL;
    struct Node *node;

    while (n) {
        node = malloc(sizeof(struct Node));
        if (!node) {
            perror("malloc failed");
            exit(1);
        }
        node->val = n;
        node->next = head;
        head = node;
        n--;
    }

    /*
    for (node = head; node; node = node->next) {
        printf("-> %d ", node->val);
    }
    printf("\n");
    */

    free_all_nodes(head);
}
