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

C free()

Why free() memory?

This manual responsibility is the core tradeoff of C's memory model -- there's no garbage collector watching for unused memory, so every successful malloc(), calloc(), or realloc() call needs a matching free() somewhere in your program's logic.

Example: Why free() memory?

c
#include <stdio.h>
#include <stdlib.h>
int main() {
	int *ptr = malloc(sizeof(int));
	*ptr = 5;
	printf("%d", *ptr);
	free(ptr);
	return 0;
}

How to use free()

free() doesn't erase the pointer variable itself, only the memory it pointed to -- so the pointer still holds the same (now-invalid) address afterward, which is why setting it to NULL immediately after freeing is considered good practice.

Example: How to use free()

c
#include <stdio.h>
#include <stdlib.h>
int main() {
	int *ptr = malloc(sizeof(int));
	*ptr = 10;
	free(ptr);
	ptr = NULL;
	printf("%d", ptr == NULL);
	return 0;
}

Double free error

This corruption happens because free() may reuse that same memory region internally for its own bookkeeping after the first free() call, so a second free() on the same address can corrupt the allocator's internal data structures.

Example: Double free error

c
#include <stdio.h>
#include <stdlib.h>
int main() {
	int *ptr = malloc(sizeof(int));
	free(ptr);
	ptr = NULL;
	printf("%d", ptr == NULL);
	return 0;
}

Dangling pointers after free()

This is one of the most notorious classes of C bugs (a use-after-free), since the pointer looks perfectly valid and dereferencing it might even appear to work by coincidence, until it silently corrupts unrelated data.

Example: Dangling pointers after free()

c
#include <stdio.h>
#include <stdlib.h>
int main() {
	int *ptr = malloc(sizeof(int));
	*ptr = 5;
	free(ptr);
	ptr = NULL;
	printf("%d", ptr == NULL);
	return 0;
}

Freeing dynamic structures

This ordering matters because once you free the outer structure, you lose any way to reach the inner pointers it contained -- freeing must always happen from the 'inside out,' starting with the most deeply nested allocations first.

Example: Freeing dynamic structures

c
#include <stdio.h>
#include <stdlib.h>
struct Node { int value; struct Node *next; };
int main() {
	struct Node *inner = malloc(sizeof(struct Node));
	struct Node *outer = malloc(sizeof(struct Node));
	outer->next = inner;
	free(inner);
	free(outer);
	printf("Freed inside-out");
	return 0;
}
🔒

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.