Memory usage - events

I recently answered a question at VBCity about a memory leakage with VB.Net:

"I am creating a class with an Event, then I instantiate the class and dispose of it. VB seems to be wasting 16 bytes each time. "

I did some research, and found something really interisting. A small VB.Net application to test this showed that the memory usage slowly increases over time. The object never gets collected. A C# test worked as expected (memory usage increases the 1st time an object is created, and then it stays the same).

When I investigated the CLR code for this, I noticed why: C#'s ctor function only created the object, while VB's did the following:

IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0007: ldsfld class [mscorlib]System.Collections.ArrayList ConsoleApplication1.LeakingClass::__ENCList
IL_000d: newobj instance void [mscorlib]System.WeakReference::.ctor(object)
IL_0012: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)

It seems to me as if it is adding the object to an arraylist (only if you have an event declaration in your class).

Is this a bug, or was it done for a reason (my best guess would be that it was done in order for other objects to still be able to respond to events raised by this object, even after it was disposed) And if it was done for a reason, is there a work-around (other than using C#)

I've included my testing code:

Imports System.Threading
Module Module1
Private Const maxGarbage As Integer = 1000

Sub Main()
Dim After As Long
Dim Begin As Long
GC.Collect()
Begin = GC.GetTotalMemory(True)
Console.WriteLine("Memory used at start: {0}", Begin)
MakeSomeGarbage()
Console.WriteLine("Memory used before collection: {0}", GC.GetTotalMemory(True))
While True
GC.Collect()
After = GC.GetTotalMemory(False)
Console.WriteLine("Memory used after full collection: {0}", After)
Console.WriteLine("Difference: {0}", After - Begin)
MakeSomeGarbage()
Console.ReadLine()
End While
End Sub

Sub MakeSomeGarbage()
Dim vt As LeakingClass
Dim i As Integer
For i = 0 To maxGarbage - 1
vt = New LeakingClass()
Next i
End Sub

Sub CreateGarbage()
Dim lc As LeakingClass
For i As Integer = 0 To maxGarbage - 1
lc = New LeakingClass()
Next i
End Sub
End Module

Public Class LeakingClass
Public Delegate Sub StatusDel()
Public Event Status As StatusDel
End Class

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
private const int maxGarbage = 1000;

static void Main()
{
long Begin;
long After;
Begin = GC.GetTotalMemory(true);
Console.WriteLine("Memory used at start: {0}", Begin);
// Put some objects in memory.
MakeSomeGarbage();
Console.WriteLine("Memory used before collection: {0}", GC.GetTotalMemory(false));

// Collect all generations of memory.
while (true)
{
GC.Collect();
After = GC.GetTotalMemory(false);
Console.WriteLine("Memory used after full collection: {0}", GC.GetTotalMemory(true));
Console.WriteLine("Difference: {0}", After - Begin);
MakeSomeGarbage();
Console.ReadLine();
}
}

static void MakeSomeGarbage()
{
LeakingClass vt;

for (int i = 0; i < maxGarbage; i++)
{
// Create objects and release them to fill up memory
// with unused objects.
vt = new LeakingClass();
}
}

}
class LeakingClass
{
public delegate void StatusDel();
public event StatusDel Status;
}



Answer this question

Memory usage - events

  • Denvas

    Take a look at: http://support.microsoft.com/ kbid=919481. The issue is described in the KB article with more details.

    Hope this helps,



  • dn8

    You are seeing the IDE leaking, it works fine in release mode. I'm not actually sure that the IDE is really leaking, you can leave it running for a while and suddenly see chunks of memory being released. The IDE debugger is known to affect the running program, especially when it has a lot of New statements.



  • Memory usage - events