← Back to C Course | Chapter 9: Memory Management | Lesson 8 of 8

C Memory Leaks

A memory leak happens when a program borrows memory and never gives it back, like never returning library books. Over time the computer runs out of space.
Syntax
c
type *ptr = malloc(sizeof(type));   // allocate on the heap
// ... use ptr ...
free(ptr);                           // release it, or the memory leaks

What is a memory leak?

Unlike a crash, a leak doesn't cause immediate visible failure -- the program keeps running, but its memory footprint grows over time, which is especially dangerous in long-running programs like servers that might run for weeks or months.

Example: What is a memory leak?

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Include general utilities (malloc, free, exit)
#include <stdlib.h>
// Program execution starts in main()
int main() {
	// Allocate memory on the heap
	int *ptr = malloc(sizeof(int));
	*ptr = 5;
	// Print formatted text to the screen
	printf("%d", *ptr);
	// Release the heap memory so it can be reused
	free(ptr);
	// Return 0 to signal that the program finished successfully
	return 0;
}

Common causes of memory leaks

A particularly sneaky cause is reassigning a pointer variable to a new malloc() result before freeing what it previously pointed to -- the old block becomes unreachable the instant the pointer is overwritten, with no error or warning.

Example: Common causes of memory leaks

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Include general utilities (malloc, free, exit)
#include <stdlib.h>
// Program execution starts in main()
int main() {
	// Allocate memory on the heap
	int *ptr = malloc(sizeof(int));
	// Release the heap memory so it can be reused
	free(ptr);
	// Allocate memory on the heap
	ptr = malloc(sizeof(int));
	*ptr = 5;
	// Print formatted text to the screen
	printf("%d", *ptr);
	// Release the heap memory so it can be reused
	free(ptr);
	return 0;
}

Detecting memory leaks

Dedicated tools like Valgrind can run your program and report exactly which allocations were never freed, along with the line of code that allocated them -- manual tracing works for small programs but doesn't scale well to large codebases.

Example: Detecting memory leaks

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Include general utilities (malloc, free, exit)
#include <stdlib.h>
// Program execution starts in main()
int main() {
	// Allocate memory on the heap
	int *ptr = malloc(sizeof(int));
	*ptr = 5;
	// Print formatted text to the screen
	printf("Run with Valgrind to detect unfreed allocations");
	// Release the heap memory so it can be reused
	free(ptr);
	// Return 0 to signal that the program finished successfully
	return 0;
}

Fixing memory leaks in loops

A loop that calls malloc() on each iteration but only frees outside the loop (or not at all) can exhaust available memory surprisingly quickly, since each iteration adds another leaked block on top of the last.

Example: Fixing memory leaks in loops

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Include general utilities (malloc, free, exit)
#include <stdlib.h>
// Program execution starts in main()
int main() {
	// Loop: repeat while the condition holds
	for (int i = 0; i < 3; i++) {
		// Allocate memory on the heap
		int *ptr = malloc(sizeof(int));
		*ptr = i;
		// Release the heap memory so it can be reused
		free(ptr);
	}
	// Print formatted text to the screen
	printf("Freed each iteration's allocation");
	// Return 0 to signal that the program finished successfully
	return 0;
}

Memory management strategies

In larger codebases, it's common to document (in a comment or the function's name itself) whether a function transfers ownership of returned memory to the caller, since ambiguity about who's responsible for freeing something is a leading cause of leaks.

Example: Memory management strategies

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Include general utilities (malloc, free, exit)
#include <stdlib.h>
int* createValue() {
	// Allocate memory on the heap
	int *ptr = malloc(sizeof(int));
	*ptr = 5;
	// Send ptr back to the caller
	return ptr;
}
// Program execution starts in main()
int main() {
	int *value = createValue();
	// Print formatted text to the screen
	printf("%d", *value);
	// Release the heap memory so it can be reused
	free(value);
	// Return 0 to signal that the program finished successfully
	return 0;
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Reassigning a pointer to a new allocation before freeing the old one, which loses the only reference.
  2. Returning early from a function before reaching the free call.
  3. Allocating memory inside a loop without freeing it each time.
Chapter Summary
  • Dynamic memory is requested at run time with malloc() and calloc(), and resized with realloc().
  • Memory you no longer need must be released with free(), otherwise it leaks.
  • The same allocation approach works for structs, and you must be careful when accessing allocated memory.
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.