Check for Memory Leaks
In this step, you'll learn how to detect and prevent memory leaks in C++ using Valgrind, a powerful memory debugging tool. Memory leaks occur when dynamically allocated memory is not properly freed, causing your program to consume increasing amounts of memory.
First, install Valgrind in the terminal:
sudo apt update
sudo apt install -y valgrind
Create a memory leak example in the WebIDE by creating memory_leak.cpp
in the ~/project
directory:
touch ~/project/memory_leak.cpp
Add the following code to memory_leak.cpp
:
#include <iostream>
class Resource {
public:
Resource(int value) : data(value) {
std::cout << "Resource created: " << data << std::endl;
}
~Resource() {
std::cout << "Resource destroyed: " << data << std::endl;
}
private:
int data;
};
void createMemoryLeak() {
// This creates a memory leak because the resource is not deleted
Resource* leak = new Resource(42);
// Missing: delete leak;
}
int main() {
// Simulate multiple memory leaks
for (int i = 0; i < 3; ++i) {
createMemoryLeak();
}
return 0;
}
Compile the program with debugging symbols:
g++ -g memory_leak.cpp -o memory_leak
Run Valgrind to detect memory leaks:
valgrind --leak-check=full ./memory_leak
Example Valgrind output:
==1988== Memcheck, a memory error detector
==1988== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1988== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==1988== Command: ./memory_leak
==1988==
Resource created: 42
Resource created: 42
Resource created: 42
==1988==
==1988== HEAP SUMMARY:
==1988== in use at exit: 12 bytes in 3 blocks
==1988== total heap usage: 5 allocs, 2 frees, 73,740 bytes allocated
==1988==
==1988== 12 bytes in 3 blocks are definitely lost in loss record 1 of 1
==1988== at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==1988== by 0x109241: createMemoryLeak() (memory_leak.cpp:19)
==1988== by 0x109299: main (memory_leak.cpp:26)
==1988==
==1988== LEAK SUMMARY:
==1988== definitely lost: 12 bytes in 3 blocks
==1988== indirectly lost: 0 bytes in 0 blocks
==1988== possibly lost: 0 bytes in 0 blocks
==1988== still reachable: 0 bytes in 0 blocks
==1988== suppressed: 0 bytes in 0 blocks
==1988==
==1988== For lists of detected and suppressed errors, rerun with: -s
==1988== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
As you can see, Valgrind detected a memory leak of 12 bytes in 3 blocks. The Resource
object created in createMemoryLeak()
was not deleted, causing the memory leak.
To fix the memory leak, modify the code to properly delete resources:
void createMemoryLeak() {
// Properly delete the dynamically allocated resource
Resource* leak = new Resource(42);
delete leak; // Add this line to prevent memory leak
}
Compile and run the program again with Valgrind to verify that the memory leak is fixed:
g++ -g memory_leak.cpp -o memory_leak
valgrind --leak-check=full ./memory_leak
==2347== Memcheck, a memory error detector
==2347== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2347== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==2347== Command: ./memory_leak
==2347==
Resource created: 42
Resource destroyed: 42
Resource created: 42
Resource destroyed: 42
Resource created: 42
Resource destroyed: 42
==2347==
==2347== HEAP SUMMARY:
==2347== in use at exit: 0 bytes in 0 blocks
==2347== total heap usage: 5 allocs, 5 frees, 73,740 bytes allocated
==2347==
==2347== All heap blocks were freed -- no leaks are possible
==2347==
==2347== For lists of detected and suppressed errors, rerun with: -s
==2347== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Key points about memory leaks:
- Always
delete
dynamically allocated memory
- Use smart pointers like
unique_ptr
and shared_ptr
- Use Valgrind to detect memory leaks
- Compile with
-g
flag for better debugging information