Main Content

CERT C++: MEM51-CPP

Properly deallocate dynamically allocated resources

Description

Rule Definition

Properly deallocate dynamically allocated resources.1

Polyspace Implementation

The rule checker checks for these issues:

  • Invalid deletion of pointer.

  • Invalid free of pointer.

  • Deallocation of previously deallocated pointer.

Examples

expand all

Issue

Invalid deletion of pointer occurs when:

  • You release a block of memory with the delete operator but the memory was previously not allocated with the new operator.

  • You release a block of memory with the delete operator using the single-object notation but the memory was previously allocated as an array with the new operator.

This defect applies only to C++ source files.

Risk

The risk depends on the cause of the issue:

  • The delete operator releases a block of memory allocated on the heap. If you try to access a location on the heap that you did not allocate previously, a segmentation fault can occur.

  • If you use the single-object notation for delete on a pointer that is previously allocated with the array notation for new, the behavior is undefined.

The issue can also highlight other coding errors. For instance, you perhaps wanted to use the delete operator or a previous new operator on a different pointer.

Fix

The fix depends on the cause of the issue:

  • In most cases, you can fix the issue by removing the delete statement. If the pointer is not allocated memory from the heap with the new operator, you do not need to release the pointer with delete. You can simply reuse the pointer as required or let the object be destroyed at the end of its scope.

  • In case of mismatched notation for new and delete, correct the mismatch. For instance, to allocate and deallocate a single object, use this notation:

    classType* ptr = new classType;
    delete ptr;

    To allocate and deallocate an array objects, use this notation:

    classType* p2 = new classType[10];
    delete[] p2;

If the issue highlights a coding error such as use of delete or new on the wrong pointer, correct the error.

Example - Deleting Static Memory
void assign_ones(void)
{
    int ptr[10];

    for(int i=0;i<10;i++)
        *(ptr+i)=1;  

    delete[] ptr;    //Noncompliant
}

The pointer ptr is released using the delete operator. However, ptr points to a memory location that was not dynamically allocated.

Correction: Remove Pointer Deallocation

If the number of elements of the array ptr is known at compile time, one possible correction is to remove the deallocation of the pointer ptr.

void assign_ones(void) 
{
    int ptr[10];

    for(int i=0;i<10;i++)
        *(ptr+i)=1;  
}
Correction — Add Pointer Allocation

If the number of array elements is not known at compile time, one possible correction is to dynamically allocate memory to the array ptr using the new operator.

void assign_ones(int num) 
{
    int *ptr = new int[num]; 

    for(int i=0; i < num; i++)
        *(ptr+i) = 1;

    delete[] ptr;
   }
Example - Mismatched new and delete
int main (void)
{
    int *p_scale = new int[5];

    //more code using scal

    delete p_scale; //Noncompliant
}

In this example, p_scale is initialized to an array of size 5 using new int[5]. However, p_scale is deleted with delete instead of delete[]. The new-delete pair does not match. Do not use delete without the brackets when deleting arrays.

Correction — Match delete to new

One possible correction is to add brackets so the delete matches the new [] declaration.

int main (void)
{
    int *p_scale = new int[5];

    //more code using p_scale

    delete[] p_scale;
}
Correction — Match new to delete

Another possible correction is to change the declaration of p_scale. If you meant to initialize p_scale as 5 itself instead of an array of size 5, you must use different syntax. For this correction, change the square brackets in the initialization to parentheses. Leave the delete statement as it is.

int main (void)
{
    int *p_scale = new int(5);

    //more code using p_scale

    delete p_scale;
}
Issue

Invalid free of pointer occurs when a block of memory released using the free function was not previously allocated using malloc, calloc, or realloc.

Risk

The free function releases a block of memory allocated on the heap. If you try to access a location on the heap that you did not allocate previously, a segmentation fault can occur.

The issue can highlight coding errors. For instance, you perhaps wanted to use the free function or a previous malloc function on a different pointer.

Fix

In most cases, you can fix the issue by removing the free statement. If the pointer is not allocated memory from the heap with malloc or calloc, you do not need to free the pointer. You can simply reuse the pointer as required.

If the issue highlights a coding error such as use of free or malloc on the wrong pointer, correct the error.

If the issue occurs because you use the free function to free memory allocated with the new operator, replace the free function with the delete operator.

Example - Invalid Free of Pointer Error
#include <stdlib.h>

void Assign_Ones(void) 
{
  int p[10];
  for(int i=0;i<10;i++)
     *(p+i)=1; 
 
  free(p);    //Noncompliant
  /* Defect: p does not point to dynamically allocated memory */
}

The pointer p is deallocated using the free function. However, p points to a memory location that was not dynamically allocated.

Correction — Remove Pointer Deallocation

If the number of elements of the array p is known at compile time, one possible correction is to remove the deallocation of the pointer p.

#include <stdlib.h>

void Assign_Ones(void)
 {
  int p[10];
  for(int i=0;i<10;i++)
     *(p+i)=1;   
  /* Fix: Remove deallocation of p */
 }
Correction — Introduce Pointer Allocation

If the number of elements of the array p is not known at compile time, one possible correction is to dynamically allocate memory to the array p.

#include <stdlib.h>

void Assign_Ones(int num) 
{
  int *p;
  /* Fix: Allocate memory dynamically to p */
  p=(int*) calloc(10,sizeof(int)); 
  for(int i=0;i<10;i++)
     *(p+i)=1; 
  free(p); 
}
Issue

Deallocation of previously deallocated pointer occurs when a block of memory is freed more than once using the free function without an intermediate allocation.

Risk

When a pointer is allocated dynamic memory with malloc, calloc or realloc, it points to a memory location on the heap. When you use the free function on this pointer, the associated block of memory is freed for reallocation. Trying to free this block of memory can result in a segmentation fault.

Fix

The fix depends on the root cause of the defect. See if you intended to allocate a memory block to the pointer between the first deallocation and the second. Otherwise, remove the second free statement.

As a good practice, after you free a memory block, assign the corresponding pointer to NULL. Before freeing pointers, check them for NULL values and handle the error. In this way, you are protected against freeing an already freed block.

Example - Deallocation of Previously Deallocated Pointer Error
#include <stdlib.h>

void allocate_and_free(void)
{

    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) return;

    *pi = 2;
    free(pi);
    free (pi);        //Noncompliant
    /* Defect: pi has already been freed */
}

The first free statement releases the block of memory that pi refers to. The second free statement on pi releases a block of memory that has been freed already.

Correction — Remove Duplicate Deallocation

One possible correction is to remove the second free statement.

#include <stdlib.h>

void allocate_and_free(void)
{

    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) return;

    *pi = 2;
    free(pi);
    /* Fix: remove second deallocation */
 }

Check Information

Group: 06. Memory Management (MEM)

Version History

Introduced in R2019a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.