Memory Leak in C++
Is your program having memory leak?
ERROR: LeakSanitizer: detected memory leaks
Oh no, memory leaks? How did it happen?
Memory leaks occurs when there is an allocation of memory in heap but no deallocation of memory after the usage. Thus, it will reduce the memory available.
Simple example
To illustrate how it can happen, we will use some simple example with the “dangerous” keyword, new
.
To run and observe the memory leak, you could inspect the memory of your local computer while running the program. Make sure your computer has at least 4GB of RAM and be ready to terminate the program!
You would observe your memory usage gradually increases until you terminate the program. This could be worse if you increase the value of 10
in BigMemory
to a bigger number for example 20
. Do note that usleep
and value of 10
in the struct of BigMemory
is to help to slow down memory leak and to only leak small portion of memory while it is still observable. Please do not try to leak too much of memory with the example or not terminating the program after you observe the grow in memory, otherwise what likely to happen would be filling up of swap partition before your computer freezes, it is up to the handling of your operating system.
From the code above, for each calling of default constructor of BadClass
, the new
operation would allocate heap memory for the BigMemory
followed by copying of the pointer to member variable ofbig_memory_
. However, since there is no deallocation of memory in the object, memory leaks.
To have a simple fix to the example, just add a destructor to delete the allocated memory when the object is destroyed.
Now running the code again, you would not see any leakage of memory.
Example with possibly hidden memory leak
Sometimes, the memory leak may be hiding in the code and less easily be identified as compared to previous example.
If there are a lof of public member function in the class, the new
keyword inside AddNewId(int id)
may be easily overlook.
Now running of the example code again with HiddenBadClass
, you would find that memory leaks again. This time it is due to allocation of BadClass
which contains BigMemory
.
If we use the previous method to delete
in destructor, we have to carefully delete each allocated memory in the map
I believe some of you might be thinking of RAII (resource acquistion is initialization) and smart pointers to simplify the code and remove the need to remember when to properly delete the allocated memory. You are right, we can do better with
Nevertheless, do note that this StillHiddenBadClass
would still be leaking of memory if the BadClass
is the initial version without the delete
in its destructor.
What can we do to avoid possible memory leak
Hence, what could we do to prevent possible memory leak? One of the answer is to let sanitizer to help you. The simple one that you could try with the example above is to add a flag during compilation, for example
Running of the code with memory leak would result in
ERROR: LeakSanitizer: detected memory leaks
However, for StillHiddenBadClass
, it may not be detected when the leaking is at the BadClass
. Hence, it is important to first understand how memory may leak in the program.
Extra possible reason of leaking
From the code above, there is no more new
or delete
, it is just a base class and derived class.
However, calling of code below
will still cause memory_leak.
Why does this happen?
This is because when the derived class object leaves the scope and got destroyed through a pointer to a base class with non-virtual destructor, the results are undefined. What normally happens at runtime is that the derived class never destroyed. Hence, the object is partially destroyed and the memory allocated for BigMemory
in DerivedClass
would leak.
The solution is this is simple, to give the base class virtual
destructor.
virtual ~BaseClass() = default;
In that case, the entire object would be destroyed including the part in derived class
That is also why we have “Item 7: Declare destructors virtual in polymorphic base classed” in Effective C++.
Here comes the end of the post, hopefully I have “leaked” some of the insight about memory leak to you.
Thanks for the reading!