Finalize Queue (WinDBG / SOS)

  • Thread starter Thread starter Steve Drake
  • Start date Start date
S

Steve Drake

All,

I am playing with WinDBG and SOS.

If I run !FinalizeQueue

I get


SyncBlock to be cleaned up: 0
----------------------------------
generation 0 has 6 finalizable objects (0x0015a370->0x0015a388)
generation 1 has 0 finalizable objects (0x0015a370->0x0015a370)
generation 2 has 0 finalizable objects (0x0015a370->0x0015a370)
Ready for finalization 0 objects (0x0015a388->0x0015a388)
All Finalizable Objects Statistics:
MT Count TotalSize Class Name
0x00935120 3 36 ConsoleApplication12.GoodClass
0x79bd9a14 3 156 System.IO.StreamWriter


why do i see GoodClass? i have called dispose on this, see my code at the
end.

I am trying to workout if my very large app is disposing objects correctly,
using winDBG sugested that it wasent, but i was sure that it was, so i wrote
this test project and it also does not seam to dispose objects.

Here is the code :



using System;
using System.Threading;



namespace ConsoleApplication12
{
class BadClass
{
public BadClass()
{
System.Console.WriteLine("Hello");
}
~BadClass()
{
System.Console.WriteLine("Sleep");
Thread.Sleep(Timeout.Infinite);
}
}

class GoodClass : IDisposable
{
public GoodClass()
{
System.Console.WriteLine("Hello");
}
~GoodClass()
{
System.Console.WriteLine("Sleep");
Thread.Sleep(Timeout.Infinite);
}
#region IDisposable Members

public void Dispose()
{
// TODO: Add GoodClass.Dispose implementation
System.Console.WriteLine("Bye ");
GC.SuppressFinalize(this);
}

#endregion
}

class EntryPoint
{
static void Main(string[] args)
{

/* BadClass b1 = new BadClass();
BadClass b2 = new BadClass();
BadClass b3 = new BadClass();
*/
GoodClass g1 = new GoodClass();
GoodClass g2 = new GoodClass();
GoodClass g3 = new GoodClass();

g1.Dispose();
g2.Dispose();
g3.Dispose();

/*
System.GC.Collect();
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
*/
Console.WriteLine("Done");
Console.ReadLine();

}

}

}
 
The documentation in MSDN about GC.SuppressFinalize is misleading.
When you call this method, you don't actually remove you object from
the finalization queue, it only turns off the bit in the object header
to NOT call the finalize method.

If an object is in the finalization queue and its finalize bit is ON,
when the object is scaned and considered garbage by the GC it is added
to the FReachable queue (a queue that holds references to objects that
are ready for their finalize method to be called). If you set the
finalize bit off the GC will not consider adding this object to the
FReachable queue and it will die like any other non finalizable object.

If you want to read more about how finalization actually works, go to
following URL for an excellent review:
http://msdn.microsoft.com/msdnmag/issues/1100/GCI/

Specifically read the section about "Forcing an Object to Clean Up", it
contains all the information you need.

So, to sum things up, the output you see in WinDbg is correct since the
object is a finalizable object and when it was created it already go
into the finalization queue.

Eran.

------------------------------------------------
http://dotnetdebug.blogspot.com - Advanced .NET Debugging Blog
The place for WinDbg and SOS tips, tricks and tutorials.



Steve said:
All,

I am playing with WinDBG and SOS.

If I run !FinalizeQueue

I get


SyncBlock to be cleaned up: 0
----------------------------------
generation 0 has 6 finalizable objects (0x0015a370->0x0015a388)
generation 1 has 0 finalizable objects (0x0015a370->0x0015a370)
generation 2 has 0 finalizable objects (0x0015a370->0x0015a370)
Ready for finalization 0 objects (0x0015a388->0x0015a388)
All Finalizable Objects Statistics:
MT Count TotalSize Class Name
0x00935120 3 36 ConsoleApplication12.GoodClass
0x79bd9a14 3 156 System.IO.StreamWriter


why do i see GoodClass? i have called dispose on this, see my code at the
end.

I am trying to workout if my very large app is disposing objects correctly,
using winDBG sugested that it wasent, but i was sure that it was, so i wrote
this test project and it also does not seam to dispose objects.

Here is the code :



using System;
using System.Threading;



namespace ConsoleApplication12
{
class BadClass
{
public BadClass()
{
System.Console.WriteLine("Hello");
}
~BadClass()
{
System.Console.WriteLine("Sleep");
Thread.Sleep(Timeout.Infinite);
}
}

class GoodClass : IDisposable
{
public GoodClass()
{
System.Console.WriteLine("Hello");
}
~GoodClass()
{
System.Console.WriteLine("Sleep");
Thread.Sleep(Timeout.Infinite);
}
#region IDisposable Members

public void Dispose()
{
// TODO: Add GoodClass.Dispose implementation
System.Console.WriteLine("Bye ");
GC.SuppressFinalize(this);
}

#endregion
}

class EntryPoint
{
static void Main(string[] args)
{

/* BadClass b1 = new BadClass();
BadClass b2 = new BadClass();
BadClass b3 = new BadClass();
*/
GoodClass g1 = new GoodClass();
GoodClass g2 = new GoodClass();
GoodClass g3 = new GoodClass();

g1.Dispose();
g2.Dispose();
g3.Dispose();

/*
System.GC.Collect();
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
*/
Console.WriteLine("Done");
Console.ReadLine();

}

}

}
 
Back
Top