Memory leaks in C++ generally occur at the time of allocates memory by using the new keyword and then forget to deallocate memory by using the delete() function or delete[] operator.
Mainly, we use the strong delete keyword to deallocate memory.
Important Note: delete operator mainly used for delete the single allocated memory space whereas delete []operator should be used for deleting array of data values.
Example of memory leakage in C++
#include <bits/stdc++.h> using namespace std; void func_with_mem_leak() { int* ptr = new int(5); } int main() { func_with_mem_leak(); return 0; }
In the above code, we have seen that the function func_with_mem_leak(), where we declared a *ptr which holds the address of a dynamically allocated array. Here, we closed the function without deallocating the dynamically allocated array, which resulted in memory leakage.
Effects with memory leakage:
Because all computers have a finite quantity of memory space, if the program has memory leakage, its memory usage will satirically increase. As a result, it will cause issues.
How to avoid Memory Leakage?
- Avoid using raw pointers
int *ptr = &a; //Avoid using raw pointers like this
- Never use raw pointers unless it’s to interface with an older lib.
#include<iostream>
#include<string> // use std::string class
using namespace std;
int main()
{
string str;
return 0;
}
- use std::string instead of char* . The std::string class handles all memory management internally. Also, it’s fast and well-optimized.
#include<iostream> using namespace std; class SmartPtr { int *ptr; public: explicit SmartPtr(int *p = NULL) { ptr = p; } ~SmartPtr() { delete(ptr); } int &operator *() { return *ptr; } }; int main() { SmartPtr ptr(new int()); *ptr = 20; cout << *ptr; /* We don't need to call delete ptr: when the object ptr goes out of scope, destructor for it is automatically called and destructor does delete ptr. */ return 0; }
- Instead of managing memory manually, try to use smart pointers where applicable. The above code explains the use of smart pointers.
#include <iostream> int main() { int *ptr = new int; // dynamically allocate an integer delete ptr; return 0; }
- The best way to avoid memory leaks in C++ is to have as few new/delete calls at the program level as possible.
Example to handle memory leakage:
#include <bits/stdc++.h> using namespace std; int main() { int* array = new int[10]; delete[] array; return 0; }
We’ve declared a process() function with a pointer *ptr in the preceding example. The address of a dynamically allocated integer array is held by the pointer *ptr. The delete function was used to correctly deallocate the dynamic space in the following line.
There is no memory waste because when we exit the function, we deallocate the memory by using the delete function.
How to detect memory leakage?
Valgrind will help you save hours of debugging time by detecting memory leaks. Many memory management and threading problems can be found using the Valgrind tools. This gives us the impression that your programs are bug-free.
When to use Valgrind?
We may always execute the program under the Valgrind tool for the tiny programs with short run times, knowing that memory issues will be identified immediately.
To check that no new issues have been introduced into the new code after major changes.
When a bug happens, we can receive immediate feedback about the bug, where it occurred, and why it occurred.
Example:
int main()
{
char *p=malloc(100);
}
Terminal Input:
$gcc -c val.c
$gcc -osingo val.o
$valgrind –tool=memcheck ./singo
Output:
==16405== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 12 from 1)
==16405== malloc/free: in use at exit: 100 bytes in 1 blocks.
==16405== malloc/free: 1 allocs, 0 frees, 100 bytes allocated.
==16405== For counts of detected errors, rerun with: -v
==16405== searching for pointers to 1 not-freed blocks.