2

As we all know this is how garbage collection should be forced

GC.Collect();
GC.WaitForPendingFinalizers();

Also C# allows us to check amount of memory currently in use.

GC.GetTotalMemory(false) // do not wait for GC

But when I call two collect and wait methods, then getting memory used I still see that memory is not cleared.

public class MemoryUsage
{
    private byte[] mmr;
    public MemoryUsage()
    {
        mmr = new byte[10000000]; // ~10 MB
    }

    ~MemoryUsage()
    {
        Console.WriteLine("Finalizer");
    }
}

public static void Main()
{
    Console.WriteLine(String.Format("Initial memory usage: {0}", GC.GetTotalMemory(false)));

    MemoryUsage m1 = new MemoryUsage();
    MemoryUsage m2 = new MemoryUsage();
    MemoryUsage m3 = new MemoryUsage();

    Console.WriteLine(String.Format("I use memory: {0}", GC.GetTotalMemory(false)));
    m1 = null;
    m2 = null;
    m3 = null;

    GC.Collect();
    GC.WaitForPendingFinalizers();

    Console.WriteLine(String.Format("I did collect and waited, but memory still: {0}", GC.GetTotalMemory(false)));

    GC.GetTotalMemory(true);

    Console.WriteLine(String.Format("I only got amount of memory and: {0}", GC.GetTotalMemory(false)));
}

App is built in Release mode, result is:

Initial memory usage: 47568
I use memory: 30062576
Finalizer
Finalizer
Finalizer
I did collect and waited, but memory still: 30070520
I only got amount of memory and: 62184

What I found is that I can call just GC.GetTotalMemory(true) instead of WaitForPendingFinalizers and all finalizers are finished.

Is there any other way to make sure that GC finished? Thanks

Alexey Klipilin
  • 1,866
  • 13
  • 29
  • 1
    But why are you use `finalizer` instead of `dispose`? `Finalizer` should be used to release unmanaged memory and I do not see that you have unmanaged memory here, try implement dispose pattern and set `byte[]` to `null` within dispose... – Johnny Mar 02 '18 at 08:06
  • 1
    Read this one https://stackoverflow.com/questions/13954829/gc-collect-and-finalize... – Johnny Mar 02 '18 at 08:10
  • @Johnny this is only for test purpose, I don't get why classes with finalizers are not cleared after WaitForPendingFinalizers – Alexey Klipilin Mar 02 '18 at 08:11
  • @Johnny I got it, have to call Collect second time, was a bit not obvious for me, thank you! – Alexey Klipilin Mar 02 '18 at 08:16
  • Exactly, I was in the middle of the comment... ;) – Johnny Mar 02 '18 at 08:17
  • The finalizer runs *after* a collection. So a class object with a finalizer cannot be collected right away, the CLR merely sets a bit in the object header to indicate that it was finalized. The next collection destroys it. – Hans Passant Mar 02 '18 at 09:41

0 Answers0