Introduction

Memory leaks in .NET applications have always been a programmer’s nightmare.
Memory leaks is the biggest problems when it comes to production servers. Productions servers normally need to run with
the least down time. Memory leaks grow slowly and after sometime they bring down the server by consuming huge chunks of memory. Most
of the time people reboot the system, make it work temporarily, and send a sorry note to the customer for the downtime. Wewill try to solve this problem here.

Avoid task manager to detect memory leaks

The first and foremost task is to confirm that there is a memory leak. Many developers use
Windows Task Manager to confirm if there is a memory leak in the application. Using
Task Manager is not only misleading but it also does not give much information about where the memory leak is.

First let’s try to understand how the Task Manager memory information is misleading. Task
Manager shows the working set memory and not the actual memory used. So what does that mean? This memory is the allocated memory and not the used memory. Adding further, some memory from the working set can be shared by other processes / applications.

So the working set memory can be bigger in amount than the actual memory used.

Using private bytes performance counters to detect memory leak

In order to get the right amount of memory consumed by the application we need to track the private bytes consumed by the application. Private bytes are those memory areas which are not shared by other applications. In order to detect private bytes consumed by an application we need to use performance counters.

Below are the steps we need to follow to track private bytes in an
application using performance counters:

Start your application which has memory leaks and keep it running.

Click Start -> go to Run, and type ‘perfmon’.

Delete all the current performance counters by selecting the counter and deleting them by hitting the
Delete button.

From the instance list select the application which you want to test memory leak for.

If your application shows a steady increase in private bytes value that means we have a memory leak issue here. You can see in the below figure how
the private bytes value is increasing steadily thus confirming that the application has
a memory leak.

The above graph shows a linear increase, but in a live implementation it can take hours to show the uptrend sign. In order to check memory leaks you need to run the performance counter for hours or probably days together on
the production server to check if there really is a memory leak.

Once we have confirmed that there is a memory leak, it’s time to investigate the root problem of the memory leak. We will divide our journey to the solution in
three phases: what, how, and where.

What: We will first try to investigate the type of memory leak, is it a managed memory leak or an unmanaged memory leak?

How: What is really causing the memory leak. Is it the connection object, some kind of file whose handle is not closed, etc.?

Where: Which function / routine or logic is causing the memory leak.

What is the type of memory leak? Total Memory = Managed memory + unmanaged memory

Before we try to understand what the type of leak is, let’s try to understand how memory is allocated in .NET applications.
The .NET application has two types of memory: managed memory and unmanaged memory. Managed memory is controlled by garbage collection while unmanaged memory is outside of
the garbage collector's boundary.

So the first thing we need to ensure is the type of memory leak: managed or unmanaged leak. In order to detect if it’s a managed leak or unmanaged leak we need to measure two performance counters.

The first one is the private bytes counter for the application which we have already seen in the previous session.

The second counter which we need to add is the ‘bytes in all heaps’. So select ‘.NET CLR memory’ in the performance object, from the counter list, select ‘Bytes in all heaps’ and the select the application which has the memory leak.

Private bytes is the total memory consumed by the application. Bytes in all heaps
is the memory consumed by the managed code. So the equation becomes something as shown in the below figure.

Unmanaged memory + Bytes in all helps = private bytes, so if we want to find out unmanaged memory we can always subtract the bytes in all
the heaps from the private bytes.

Now we will make two statements:

If the private bytes increase and bytes in all heaps remain constant that means it’s an unmanaged memory leak.

If the bytes in all heaps increase linearly that means it’s a managed memory leak.

Below is a typical screenshot of an unmanaged leak. You can see the private bytes are increasing while bytes in heaps remain constant:

Below is a typical screenshot of a managed leak. Bytes in all heaps are increasing.

How is the memory leak happening?

Now that we have answered what type of memory is leaking it’s time to see how the memory
is leaking. In other words who is causing the memory leak?

So let’s inject an unmanaged memory leak by calling the Marshal.AllocHGlobal function. This function allocates unmanaged memory and thus injects
an unmanaged memory leak in the application. This command is run within the timer number of times to cause
a huge unmanaged leak.

It’s very difficult to inject a managed leak as GC ensures that the memory is reclaimed. In order to keep things simple we simulate a managed memory leak by creating
a lot of brush objects and adding them to a list which is a class level variable. It’s a simulation and not a managed leak. Once the application is closed, this memory will be reclaimed.

Where is the memory leak?

Once you know the source of the memory leak, it’s time to find out which logic is causing the memory leak. There is no automated tool to detect
the logic which causes memory leaks. You need to manually go in your code and take the pointers provided by ‘debugdiag’ to conclude
in which places the issues are.

For instance from the report it’s clear that AllocHGlobal is causing the unmanaged leak while one of the objects of GDI is causing the managed leak. Using these details we need to go in the code to see where exactly the issue lies.

Source code

You can download the source code from the top of this article which can help you inject
a memory leak.

It would be unfair on my part to say that the above article is completely my knowledge. Thanks for all the lovely people
listed here who have written articles so that one day someone like me can be benefit
from them.

http://blogs.msdn.com/tess/: A great blog by a lovely lady Tess on debuggers. There are some great labs on memory leak detection using
WinDbg, do not miss it. Tess, God bless you, your blog rocks like anything.