Avoid Memory Leaks in C++

  1. Use the delete Operator to Free Each new-Allocated Memory Block
  2. Use std::unique_ptr to Automatically Free Heap Objects

This article will demonstrate multiple methods about how to avoid memory leaks in C++.

Use the delete Operator to Free Each new-Allocated Memory Block

Memory leaks are a common problem for the programs that directly interact with the raw dynamic memory interface, which puts a burden on the programmer to free each allocated memory with the corresponding method. There are multiple interfaces for memory management accessible in C++ along with some platform-specific system calls, which essentially represent the lowest level functions that can be utilized for this purpose. In most cases, the regular program should only use language-specific facilities like new and delete operators for manual memory management or use smart pointers for automatic memory deallocation.

The most vulnerable method for memory leaks is using the new/delete operators to directly manage heap memory. Note that every pointer returned from the new call should be passed to the delete operator to release the corresponding memory blocks back to the system, or the memory might get exhausted. For example, the following program allocates a 10-element char array and does not free it before the program exit. Thus, the program is said to suffer from a memory leak.

#include <iostream>

using std::cout;
using std::endl;

constexpr int SIZE = 10;

int main()
{
    char *arr = new char[SIZE];

    for(int i = 0; i < SIZE; ++i) {
        arr[i] = (char)(65 + i);
        cout << arr[i] << "; ";
    }
    cout << endl;

    return EXIT_SUCCESS;
}

Memory leaks can be detected using the valgrind program, which is a command-line utility and can be executed on a compiled program file. Note that Valgrind is actually a set of multiple tools, one of which happens to be a memory checking utility. The following command can be issued to investigate memory leaks.

valgrind --tool=memcheck --leak-check=full ./program

Once it has done checking, the following output is printed. Notice that, since we did not call delete on the arr pointer, the whole array resulted in unfreed memory hence the record - definitely lost: 10 bytes in leak summary. The latter is the actual size of the 10-element char array.

==13732== HEAP SUMMARY:
==13732==     in use at exit: 10 bytes in 1 blocks
==13732==   total heap usage: 3 allocs, 2 frees, 73,738 bytes allocated
==13732==
==13732== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==13732==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==13732==    by 0x1091FE: main (tmp.cpp:11)
==13732==
==13732== LEAK SUMMARY:
==13732==    definitely lost: 10 bytes in 1 blocks
==13732==    indirectly lost: 0 bytes in 0 blocks
==13732==      possibly lost: 0 bytes in 0 blocks
==13732==    still reachable: 0 bytes in 0 blocks
==13732==         suppressed: 0 bytes in 0 blocks
==13732==
==13732== For lists of detected and suppressed errors, rerun with: -s
==13732== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Use std::unique_ptr to Automatically Free Heap Objects

The previous example code can be fixed by the delete [] arr; statement before the program exit. Although, another option is to utilize one of the smart pointers e.g. std::unique_ptr. Smart pointer object can be initialized with the given type and stores the pointer returned from the new operator. The only difference from the regular pointer is that std::unique_ptr associated memory region does not need to be delete-d explicitly. Instead, the compiler takes care of the deallocation once the object goes out of the scope.

#include <iostream>
#include <memory>

using std::cout;
using std::endl;

constexpr int SIZE = 10;

int main()
{
    std::unique_ptr<char[]> arr(new char[SIZE]);

    for (int i = 0; i < SIZE; ++i) {
        arr[i] = (char)(65 + i);
        cout << arr[i] << "; ";
    }
    cout << endl;

    return EXIT_SUCCESS;
}
Contribute
DelftStack is a collective effort contributed by software geeks like you. If you like the article and would like to contribute to DelftStack by writing paid articles, you can check the write for us page.

Related Article - C++ Memory

  • Use malloc vs new Allocators in C++