Memory Leakage in C: Common Pitfalls and Prevention Strategies
Suppose we allocate memory using either malloc(), calloc() or realloc(), our program runs perfectly, no errors, no warnings, but still after some time system becomes slow or crashes. Why? The reason is something called Memory Leak.
A memory leak occurs when a program allocates memory dynamically but does not free it, causing the heap memory to become unreachable and remain occupied without being released back to the system.
The “Unreachable” mean, memory block still exists in heap but no pointer is pointing to that block. So, we cannot access and free it. That memory is permanently lost until program ends.
- Memory leak is a silent bug.
Memory leak happens when a program allocates memory dynamically but forgets to free it.
Or
When heap memory becomes unreachable but is not released, it is called memory leakage.
Stack vs Heap:

Stack Segment
- Used for local variables, function parameters, and return addresses.
- Each time a function is called, a stack frame is created.
- Memory managed automatically, stack frames are pushed when functions are called and popped when they return.
- No memory leak possible.
Heap Segment
- Manually managed by functions like malloc(), calloc(), realloc(), and free().
- Allocated using malloc(), calloc(), realloc().
- Must be release using free().
- Memory leak possible.
BASIC EXAMPLE OF MEMORY LEAK:
#include<stdio.h>
#include<stdlib.h>
void main()
{
int *ptr = (int*)malloc(5*sizeof(int));
…………………………………
…………………………………
…………………………………
// forgot to release memory
getch();
}
Here, memory is allocated in the heap using malloc(). The program terminates without calling free(ptr);, the allocated memory is not returned to the system. As a result, that memory remains occupied and unused, which leads to a memory leak.
TYPES OF MEMORY LEAK SITUATIONS:
- Forgetting free().
- Pointer Overwritten.
- Lost Pointer.
- Early Return in Function.
- Inside Loop.
- Not Freeing Complex Data Structures Properly.
| LEAK SITUATION | DESCRIPTION | EXAMPLE |
|---|---|---|
| Forgotten free() | Memory is allocated but never released back to the system. | int *ptr=malloc(20); // free(ptr); |
| Pointer Overwritten | The pointer holding allocated memory is reassigned before freeing the previous block, causing the old block to become unreachable. | int *ptr=malloc(30); ptr=malloc(50); Now first 30 bytes memory block is lost forever. You no longer have its address. |
| Lost Pointer (Set to NULL) | The pointer is set to NULL before freeing memory, making the allocated block unreachable. | int *ptr=malloc(100); ptr=NULL; |
| Early Function Return | Function exits before calling free(), so allocated memory remains unreleased. | int *ptr=malloc(50); …………………….. if(error) return 0; …………………….. …………………….. free(ptr); …………………….. Whenever function exits before free(), memory leak occurs. |
| Memory Allocation Inside Loop | Memory is allocated repeatedly inside a loop without freeing it in each iteration. | while(1) { int *ptr=malloc(100); } Each iteration allocates new memory and no free. Infinite memory consumption and system will eventually crash. |
| Not Freeing Complex Data Structures | In structures like linked lists or trees, only part of the structure is freed, leaving remaining nodes leaked. | free(head); In linked list, each node is allocated using malloc. If free only head pointer, frees only first node and remaining nodes leaked. Must free node-by-node. while(head != NULL) { temp=head; head=head->next; free(temp); } |
Why Memory Leak is Dangerous?
- Memory leak does not show error immediately. It is a silent bug.
- Wastes RAM.
- Slows down system.
- Causes program crash.
- Dangerous in long-running programs like servers, embedded systems etc.
Prevention Strategies / Prevent Memory Leak:
- Every malloc must have exactly one free.
- Free memory before reassigning pointer.
- Set Pointer to NULL After Free.
- Check all exit or return paths to make sure memory is freed before return.
Memory Leak vs Dangling Pointer:
| MEMORY LEAK | DANGLING POINTER |
|---|---|
| Memory exists but pointer is lost and result is we cannot access memory. | Pointer exists but memory is already freed and result is pointer is pointing to invalid memory. |
| Causes wastage of heap memory. | Causes undefined behavior and possible program crash. |
| Happens when free() is not called. | Happens when free() is called but pointer is not set to NULL. |
| #include<stdio.h> #include<conio.h> #include<stdlib.h> void main() { int *ptr; ptr=(int*)malloc(sizeof(int)); *ptr=22; printf("Value : %d\n",*ptr); ptr=(int*)malloc(5*sizeof(int)); ptr=NULL; getch(); } | #include<stdio.h> #include<conio.h> #include<stdlib.h> int* arrayAllocation(); void main() { int *arr; arr=arrayAllocation(); printf("Address : %u\n",arr); getch(); } int* arrayAllocation() { int *ptr; int n; printf("Enter Array Size : "); scanf("%d",&n); ptr=(int*)malloc(n*sizeof(int)); printf("Address : %u\n",ptr); free(ptr); return(ptr); } |
Why C Does Not Have Garbage Collection (GC)?
C is a low-level language used for system programming like operating systems, kernels, and drivers, where full control over memory and high performance are essential.
If Garbage Collection (GC) were included, it could reduce performance and make memory behavior harder to control. Therefore, C leaves memory management entirely to the programmer.
C language gives, power and responsibility while Garbage Collection languages (Java, Python, C#) give safety and convenience.
- Safety means the programmer is protected from common memory-related errors.
- Convenience means memory management becomes easier for the programmer.
