65.9K
CodeProject is changing. Read more.
Home

Memory Leak Caused by Fragmentation

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.08/5 (19 votes)

Jul 29, 2005

2 min read

viewsIcon

102800

downloadIcon

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:

Sample Image

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:

Sample Image

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.