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:
CPtrArray g_oBuffer;
MyData* oData = new MyData();
g_oBuffer.Add(oData);
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:
MyData* oData = (MyData*)MyObjectPool::GetNew();
g_oBuffer.Add(oData);
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>
StrPool MyPool(10);
CString* pStr = MyPool.getNewObj();
MyPool.deleteObj(pStr);
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.