Wednesday, December 07, 2005

Memory leaks in .Net

.Net was supposed to make memory leaks a thing of the past. Turns out they can happen in C#, even pure .Net code that has no COM objects or unmanaged codes.

The culprit is async sockets.

The the buffer we pass to Socket.BeginReceive gets "pinned" in memory, preventing GC memory compaction. Since all new allocation uses the top of the stack, .Net has no choice but to keep allocating more Private Bytes.

Here's a thread about someone else having this problem

http://groups.google.ca/group/microsoft.public.dotnet.framework/brows...

Strangely, the addition of a Thread.Sleep(1) seems to make the memory
leak go away.

Basically, here is the BeginReceive callback function:

void AsyncReceiveCallback(IAsyncResult result)
{
VeoAsyncIOInfo thisConnection = (VeoAsyncIOInfo)result.AsyncState;
int num_read = thisConnection.m_socket.EndReceive(result);
if (0 != num_read) {
ProcessNewData(thisConnection.m_buffer, num_read,
thisConnection.m_socket);
}

Thread.Sleep(1); //hack hack hack

thisConnection.m_socket.BeginReceive(thisConnection.m_buffer, 0,
MAXMSGSIZE, SocketFlags.None, new AsyncCallback(AsyncReceiveCallback),
thisConnection);
}

No comments: