Main Content

Memory leak

Memory allocated dynamically not freed

Description

This defect occurs when you do not free a block of memory allocated through malloc, calloc, realloc, or new. If the memory is allocated in a function, the defect does not occur if:

  • Within the function, you free the memory using free or delete.

  • The function returns the pointer assigned by malloc, calloc, realloc, or new.

  • The function stores the pointer in a global variable or in a parameter.

Risk

Dynamic memory allocation functions such as malloc allocate memory on the heap. If you do not release the memory after use, you reduce the amount of memory available for another allocation. On embedded systems with limited memory, you might end up exhausting available heap memory even during program execution.

Fix

Determine the scope where the dynamically allocated memory is accessed. Free the memory block at the end of this scope.

To free a block of memory, use the free function on the pointer that was used during memory allocation. For instance:

ptr = (int*)malloc(sizeof(int));
...
free(ptr);

It is a good practice to allocate and free memory in the same module at the same level of abstraction. For instance, in this example, func allocates and frees memory at the same level but func2 does not.

void func() {
  ptr = (int*)malloc(sizeof(int));
  {
    ...
  }
  free(ptr);
}

void func2() {
  {
   ptr = (int*)malloc(sizeof(int));
   ...
  }
  free(ptr);
}
See CERT-C Rule MEM00-C.

Examples

expand all

#include<stdlib.h>
#include<stdio.h>

void assign_memory(void)
{
    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) 
        {
         printf("Memory allocation failed");
         return;
        }


    *pi = 42;
    /* Defect: pi is not freed */
}

In this example, pi is dynamically allocated by malloc. The function assign_memory does not free the memory, nor does it return pi.

Correction — Free Memory

One possible correction is to free the memory referenced by pi using the free function. The free function must be called before the function assign_memory terminates

#include<stdlib.h>
#include<stdio.h>

void assign_memory(void)
{
    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) 
        {
         printf("Memory allocation failed");
         return;
        }
    *pi = 42;

    /* Fix: Free the pointer pi*/
    free(pi);                   
}
Correction — Return Pointer from Dynamic Allocation

Another possible correction is to return the pointer pi. Returning pi allows the function calling assign_memory to free the memory block using pi.

#include<stdlib.h>
#include<stdio.h>

int* assign_memory(void)
{
    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) 
        {
            printf("Memory allocation failed");
            return(pi);
        }
    *pi = 42;

    /* Fix: Return the pointer pi*/
    return(pi);                   
}
#define NULL '\0'

void initialize_arr1(void)
{
    int *p_scalar = new int(5);
}

void initialize_arr2(void)
{
    int *p_array = new int[5];
}

In this example, the functions create two variables, p_scalar and p_array, using the new keyword. However, the functions end without cleaning up the memory for these pointers. Because the functions used new to create these variables, you must clean up their memory by calling delete at the end of each function.

Correction — Add Delete

To correct this error, add a delete statement for every new initialization. If you used brackets [] to instantiate a variable, you must call delete with brackets as well.

#define NULL '\0'

void initialize_arrs(void)
{
    int *p_scalar = new int(5); 
    int *p_array = new int[5];  

    delete p_scalar;
    p_scalar = NULL;

    delete[] p_array;
    p_scalar = NULL;
}

Result Information

Group: Dynamic memory
Language: C | C++
Default: Off
Command-Line Syntax: MEM_LEAK
Impact: Medium

Version History

Introduced in R2013b