Garbage collection is implemented in the majority of high-level programming languages. In C programming
language, there are no signs of automatic garbage collection. Thus, programmers of this low-level language
are responsible for the memory management that occurs within a program. Memory leaks are, in a way, a
consequence of poor memory management.
Take a look at the 7 Q&As below to understand this and more.
A memory leak is a block of dynamically allocated memory that is not freed and that has lost all the references to it. In C programming
language this occurs, when heap memory is dynamically allocated
with functions, like malloc or calloc but not freed (with the function free) when this memory is no longer needed. Or when
dynamically allocated memory is made inaccessible before it is freed, even though, it is still needed.
2. What types of programming mistakes
lead to memory leaks?
There are three common mistakes that lead to memory leaks:
[1] Improper handing of a return value.
Example 1: A memory leak because of an unhandled return value.
#include <stdio.h>
#include <stdlib.h>
char*get_ptr()
{
char*ptr = (char *)malloc(10);
returnptr;
}
intmain()
{
get_ptr(); //pointer to heap memory is lost
return0;
}
In the example above (Example 1), a memory leak occurs because a pointer is lost that contains
the address to the dynamically allocated memory block. To fix this memory leak, we need to handle the
return value of the function get_ptr and free it when the
memory is
no longer necessary. Just like it is done in the example below (Example 2).
Example 2: Proper memory management of the returned value.
#include <stdio.h>
#include <stdlib.h>
char*get_ptr()
{
char*ptr = (char *)malloc(10);
returnptr;
}
intmain()
{
char*ptr = get_ptr();
// ...
free(ptr);
return0;
}
Note: make sure to free dynamically allocated memory
after you no longer need it.
[2] Another common memory management mistake is improper freeing of an array of pointers.
Example 3: A memory leak because of improper freeing of an array of pointers.
free(*ptr_2D); //this pointer cannot be accessed anymore
return0;
}
Here (Example 3), a memory leak is caused by the freeing of the ptr_2D array (on line 7) because it contains elements that are not
freed at that point. In this way,
dynamically allocated memory (on line 6) is no longer accessible by the program. To fix this
memory leak, we need to free the element within the ptr_2D
array
first. Just like you can see below (example 4).
Example 4: Freeing an array with a dynamically allocated pointer in C.
free(*ptr_2D); //freeing elements within the array first
free(ptr_2D); //now the array of pointers can be freed without memory
leaks
return0;
}
[3] One more common mistake that leads to memory leaks is reassignment. When we reassign a pointer that holds an address to an allocated memory, we can get a memory leak in C programming language.
Example 5: A memory leak because of reassignment.
#include <stdio.h>
#include <stdlib.h>
intmain()
{
int*ptr = (int *)calloc(5, sizeof(int));
ptr = NULL;
free(ptr); // memory allocated on line 5 is not accessible
anymore
return0;
}
In the example above (Example 5), a pointer ptr is
pointed to NULL (on line 6). This causes a memory leak
because the allocated memory (on line 5) cannot be freed anymore. To fix this
memory leak, we need to free (example 6) or set another pointer to (example 7) the allocated memory before assigning the pointer
ptr to NULL.
Example 6: Freeing before reassignment.
#include <stdio.h>
#include <stdlib.h>
intmain()
{
int*ptr = (int *)calloc(5, sizeof(int));
free(ptr);
ptr = NULL;
return0;
}
Example 7: Setting another pointer to the allocated memory address before reassignment.
#include <stdio.h>
#include <stdlib.h>
intmain()
{
int*ptr = (int *)calloc(5, sizeof(int));
int*another_ptr = ptr;
ptr = NULL;
// ...
free(another_ptr);
return0;
}
Note: it is safe to free a NULL pointer.
3. Do memory leaks occur on the stack in C?
No. Memory leaks do not occur on the stack in C because stack objects have automatic storage duration. Whenever an object leaves its scope, it is automatically freed.
Memory leaks only occur because of the improper handling of those objects that have dynamic storage duration. In other words, memory leaks can only occur with heap objects.
This
applies to every path of execution. This means that if an error occurs, dynamically allocated
memory should
still be freed. Just like it is freed in the example below (consider line 13).
Example 8: Freeing on every path of execution (free on line 13 prevents a memory leak in case of error).
#include <stdio.h>
#include <stdlib.h>
voidtake_action()
{
int*ptr = (int *)malloc(sizeof(int) * 5);
if(ptr == NULL)
{
return;
}
int*ptr_2 = (int *)malloc(sizeof(int) * 5);
if(ptr == NULL)
{
free(ptr); //without a free call here, error above would cause a memory leak
return;
}
// ...
free(ptr);
free(ptr_2);
}
intmain()
{
take_action();
return0;
}
5. In what types of applications are memory
leaks especially dangerous?
Memory leaks are never desirable, to say the least. However, they are way more dangerous and detrimental
to long-running application. Such applications, among others, include (1) servers, (2) browsers and (3) graphic
editors.
In these and other long-running applications memory leaks have a higher probability to result in crashes, given that the number of leaks continuously grow over time.
6. How to find memory leaks in C?
In order to find memory leaks, you may reserve to, at least, two options. One is to use runtime detection
tools like Valgrind or Dr. Memory. Two, implement a pair of counters of allocated and deallocated memory or
of malloc and free
function calls.
Example 9: Counters for free and malloc calls
static unsigned int Allocated = 0;
static unsigned int Deallocated = 0;
void*Allocate_memory (size_t size)
{
void*ptr = NULL;
ptr = malloc(size);
if(NULL != ptr)
{
++Allocated;
}
else
{
//Log error
}
return(ptr);
}
voidDeallocate_memory (void *ptr)
{
if(ptr!= NULL)
{
free(ptr);
++Deallocated;
}
}
intIs_all_memory_freed ()
{
returnAllocated == Deallocated;
}
Using the counter functions (example 9) helps you to keep track of all the allocations and deallocations within your program. The Is_all_memory_freed function informs you, if all the allocated memory is freed.
Note: counter functions add overhead to a C program.
7. Do memory leaks pose security risks?
Yes. Memory leaks pose security risks to publicly accessible applications. If a malicious user can
cause a memory leak by a certain sequence of actions in a publicly accessible application (think of a web-browser or a router),
then such an application can be negatively affected by the malicious users.
Summary
To sum it all up, memory leaks are lost references to memory addresses that are not freed. These lost references, in turn, downgrade your software and make it more prone to crashes and vulnerable to malicious attacks.
To improve the quality of your programs, prevent memory leaks by following the best practices and utilize a tracking option for memory leaks. So that your application can be memory leaks free.
quizzes and articles!
Please fill out the form below to stay up-to-date to our newest interactive
articles with quizzes.