A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
A memory leak is allocated memory that is never freed. The program loses all pointers to the block. The memory cannot be reclaimed. The block is gone until the process exits. A small leak in a short-lived tool is harmless. A small leak in a server that runs for months is a death sentence. The process grows until the OS kills it or the system runs out of memory. Leaks are the most common memory bug in C, and the easiest to prevent with the right tools and habits.
#include <stdio.h>#include <stdlib.h>#include <string.h>char *process_line(const char *input) {char *buffer = malloc(strlen(input) + 1);if (!buffer) return NULL;strcpy(buffer, input);for (char *p = buffer; *p; p++) {if (*p >= 'a' && *p <= 'z') *p -= 32;}return buffer;}int main(void) {for (int i = 0; i < 5; i++) {char *result = process_line("hello world");printf("Result: %s\n", result);}return 0;}
ASan's LeakSanitizer reports 60 bytes leaked in 5 allocations, all from process_line. The caller printed the result but never freed it. The fix is one line: free(result) after the printf. The tool tells you the allocation site, the size, and the count. You do not need to guess where the leak is.
#include <stdio.h>#include <stdlib.h>#include <string.h>char *process_line(const char *input) {char *buffer = malloc(strlen(input) + 1);if (!buffer) return NULL;strcpy(buffer, input);for (char *p = buffer; *p; p++) {if (*p >= 'a' && *p <= 'z') *p -= 32;}return buffer;}int main(void) {for (int i = 0; i < 5; i++) {char *result = process_line("hello world");if (result) {printf("Result: %s\n", result);free(result);result = NULL;}}return 0;}
No leak report. The free(result) releases each allocation. The result = NULL prevents accidental use-after-free. The ownership model is clear: process_line allocates, the caller frees. This contract must be documented in the function's comment. Every allocation has exactly one owner responsible for freeing it.
Free at the same scope level where you allocated. If a function allocates and returns, document that the caller owns the free. Use goto cleanup for multi-resource functions. Run ASan with leak detection in every test run. Run Valgrind periodically for a deeper analysis. In long-running servers, monitor RSS growth over time. A flat line means no leaks. A rising line means you have work to do.
Memory leaks are a discipline problem, not a language problem. The tools exist. The patterns exist. The cost of a leak in production is real: downtime, OOM kills, customer impact. Free what you allocate. Document who frees what. Run the sanitizers. Next: function pointers, the mechanism behind callbacks, dispatch tables, and runtime polymorphism in C.
Finish the lesson once you have worked through the material. This awards ★ 40 XP.