I am trying to write a class that wraps a buffer allocated with Marshal.AllocHGlobal
. I implemented the IDisposable
interface, and added a finalizer that should release the memory when I don't need it anymore (when the object goes out of scope).
When I test the class, the GC does not call the finalizer or the Dispose method of my classes, even though they are out of scope. As a result, I get an OutOfMemoryException
.
Why does the GC not call the finalizer, and why does the memory not get freed?
Here is a short example that illustrates the problem. In the sample, there is nothing written to the console (except Unhandled Exception: OutOfMemoryException.
)
class Buffer : IDisposable
{
public IntPtr buf { get; set; }
public Buffer()
{
buf = Marshal.AllocHGlobal(4 * 1024 * 1024);
}
~Buffer()
{
Console.WriteLine("Finalizer called");
Dispose(false);
}
public void Dispose()
{
Console.WriteLine("Dispose called");
Dispose(true);
GC.SuppressFinalize(this);
}
internal virtual void Dispose(bool disposing)
{
if (buf != IntPtr.Zero)
{
Console.WriteLine("Releasing memory");
Marshal.FreeHGlobal(buf);
buf = IntPtr.Zero;
}
}
}
class Program
{
static void Main(string[] args)
{
while(true)
{
Buffer b = new Buffer();
Thread.Sleep(20);
}
}
}
EDIT: Here is the .NET performance counters for my test program when it crashes: