Memory leak in C++ and How to avoid it?


Reading time: 35 minutes

Memory leakage in C++ occurs when we allocates memory by using new keyword and forgets to deallocate the memory by using delete() function or delete[] operator.

Sometimes we use wrong delete keyword to deallocate memory.

πŸ‘‰ Important : The delete operator should be used to free a single allocated memory space, whereas the delete [] operator should be used to free an 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 πŸ‘† example, we wrote a function func_with_mem_leak(), where we declared a pointer *ptr which holds the address of a dynamically allocated array. Here, we terminated the function without deallocating the dynamically allocated array, which resulted in memory leakage.

Effects with memory leakage

If a program has memory leakage, then its memory usage will satirically increase since all systems have limited amount of memory space. Hence it will create problems.

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; 
} 

In the above πŸ‘† example, we have declared a process() function, which has a pointer *ptr. Pointer *ptr holds the address of a dynamically allocated integer array. In the next line, we have deallocated the dynamic space by using the delete function perfectly.

No memory is wasted because when we are coming out from the function we are deallocating the memory by using delete function.

How to detect memory leakage?

Valgrind will save hours of debugging time spent on analysing memory leakage. With valgrind tools we can detect many memory management and threading bugs. This gives us a feel that your programs are free of many common bugs.

When to use Valgrind?

  • For small programs with short run-times- We can always run the program under a valgrind tool, knowing that memory bugs will be found immediately.
  • After big changes- To ensure new bugs haven’t been introduced in the new code.
  • When a bug occurs- We can get instant feedback about the bug, where it has occurred, and why.

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.

Questions

1. Which operator should be used to free an array of data values?

delete []
delete
del()
None of the options
The delete [] operator should be used to free an array of data values.