Memory Leak Caused by Fragmentation






3.08/5 (19 votes)
Jul 29, 2005
2 min read

102800

656
This article shows the effect of Memory Fragmentation and provides a generic object pool class.
Introduction
Some days ago, I finished fixing a bug called "memory leak" that I think I'll never forget during my career.
My program was about a real-time monitor that read data from a server and viewed graphs. My program met the "memory leak" problem when data throughput was too heavy. I remember, every 100 ms the program had to read about 2 Kb data. And then, after only a day, my program ran out of virtual memory although the private bytes still looked pretty good on the Performance tool.
I tried to detect memory leak by using a lot of tools, from free of charge tools to trade tools as I was used to do before, but none of the tools could find out any memory leak.
Background
Problem
Now, let's consider the problem:
//The following was a global buffer CPtrArray g_oBuffer; //... //Any time new data arrived, I allocated //a new memory and added it to the buffer MyData* oData = new MyData(); g_oBuffer.Add(oData); //... //When old data wasn't needed anymore, I removed it MyData* oData = (MyData*)g_oBuffer.GetAt(0); g_oBuffer.RemoveAt(0); delete oData; //...
Everything looked fine and that was the reason why my program's private bytes looked stable. But unfortunately, after only a day, I met a memory exception and saw the virtual bytes reach the 2 GB limitation.
The Performance monitor looked like below:
Solution
Instead of allocating memory one by one, I decided to pre-allocate a large amount of memory into an object pool and use it when necessary. Then, my code became like this:
//Any time new data arrived, I got a pre-allocated memory //from the object pool and added it to the buffer //MyData* oData = new MyData(); MyData* oData = (MyData*)MyObjectPool::GetNew(); g_oBuffer.Add(oData); //... //When old data wasn't needed anymore, I removed it //and returned the memory to the object pool MyData* oData = g_oBuffer.RemoveAt(0); //MyData* oData = g_oBuffer.RemoveAt(0); MyObjectPool::Delete(oData); //...
After applying this solution, I was impressed with the result as below:
Using the code
In order to provide a generic object pool, I re-implemented the object pool as a template class. With this article, I'd just like to show a real experience on Memory Fragmentation and a solution which has been applied successfully. Besides, I only did a few tests on my code. Therefore, it may still have some bugs remaining. If anyone could find out a bug, please send a feedback to me. I will really appreciate it.
To use this generic object pool, all you have to do is:
#define StrPool CObjectPoolImpl<CString> //... //Create a new pool StrPool MyPool(10); //Size in Mega byte //... //Create a new CString object CString* pStr = MyPool.getNewObj(); //... //Delete CString object when it's not used any more MyPool.deleteObj(pStr); //... //Empty the pool MyPool.deleteAllObj();
References
From the bottom of my heart, I would like to say "thanks" to the author Danny Kalev who has written this article. This one was very short but cool enough to describe what a memory fragmentation is.