Detecting Leaks
memcheck basics.
Detecting Leaks is a free C Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What A Leak Is
A memory leak happens when you allocate heap memory with malloc, calloc, or realloc and lose every pointer to it before calling free.
The block stays reserved but unreachable until the process exits. In long-running programs, leaks accumulate until memory runs out.
A Minimal Leak
This program leaks one block of 40 bytes.
The pointer p is a local variable. When main returns, p disappears but the heap block it pointed at is never freed.
#include <stdlib.h>
int main(void) {
int *p = malloc(10 * sizeof(int));
p[0] = 1;
return 0; /* never free(p) */
}Running memcheck
memcheck is the default tool, so you can leave the tool name off.
Add --leak-check=full to get a stack trace for each leaked allocation.
gcc -g -O0 -o leak leak.c
valgrind --leak-check=full ./leakThe Leak Summary
At exit Valgrind prints a LEAK SUMMARY. For the program above it reads roughly:
definitely lost: 40 bytes in 1 blocks
The trace points to the exact malloc call site, so you know precisely which allocation was never freed.
The Four Leak Categories
memcheck classifies lost memory into four buckets:
- definitely lost — no pointer remains; a true leak
- indirectly lost — reachable only through a definitely-lost block
- possibly lost — only an interior pointer remains
- still reachable — a pointer exists at exit but you never freed it
Definitely vs Still Reachable
definitely lost is the urgent category: those bytes can never be recovered while the program runs.
still reachable is milder. The block is leaked at exit but a global or static pointer still references it, so it is usually a one-time allocation you simply never bothered to free.
Indirect Leaks
When you lose the head of a linked structure, every node becomes unreachable.
The head shows as definitely lost and the rest as indirectly lost. Fixing the root cause, the lost head, recovers all of it.
struct Node { int v; struct Node *next; };
struct Node *make(void) {
struct Node *h = malloc(sizeof *h);
h->next = malloc(sizeof *h);
h->next->next = NULL;
return h;
}
/* if the caller drops the returned head, both nodes leak */The Fixed Version
Free what you allocate. This version leaks nothing.
Under Valgrind it reports All heap blocks were freed -- no leaks are possible.
#include <stdlib.h>
int main(void) {
int *p = malloc(10 * sizeof(int));
p[0] = 1;
free(p);
return 0;
}Counting Allocations
Even without leaks, the HEAP SUMMARY tells you how busy your program was:
total heap usage: 1 allocs, 1 frees, 40 bytes allocated
When allocs and frees match, you have a clean run. A mismatch is your first clue something escaped.
Showing Reachable Blocks
By default memcheck does not list still reachable blocks in detail. To audit those too, add:
--show-leak-kinds=all
This forces a trace for every category, useful when you want a program that frees absolutely everything before exit.
valgrind --leak-check=full --show-leak-kinds=all ./leakLeaks On Error Paths
The sneakiest leaks hide on early-return paths. Here, if the second allocation fails, the first block leaks.
Run-of-the-mill testing rarely hits these branches, but memcheck catches them whenever the path executes. Always free what you hold before returning on error.
char *a = malloc(100);
char *b = malloc(100);
if (!b) {
/* bug: a is leaked here */
return -1;
}
/* fix: free(a); before returning */Quick Check
Pick the leak category that demands the most urgent attention.
Recap
You can now detect leaks with memcheck:
- Run
valgrind --leak-check=full ./progon a-gbinary - Read the LEAK SUMMARY and HEAP SUMMARY
- Prioritize definitely lost, then chase indirect leaks to their root
- Use
--show-leak-kinds=allto audit still-reachable blocks
Next: invalid memory access.
Frequently asked questions
Is the “Detecting Leaks” lesson free?
Yes — the full text of “Detecting Leaks” is free to read here on the web, and the C Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C Academy course, upgrade to CoddyKit PRO.
What will I learn in “Detecting Leaks”?
memcheck basics. You practise C Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C Academy?
No prior experience is required. C Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Detecting Leaks” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C Academy lesson?
Yes. Every C Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Why Valgrind
- Detecting Leaks
- Invalid Access
- Reading Reports