0

I have a WPF application that allows the user to open, close and reopen an arbitrary amount of child windows.

Using VS2015's integrated memory profiler I found out that a certain type of child window, let's call it ProblematicChildWindow, always stays in memory after having been closed, so its instances add up in case of frequent close and reopen actions. Unfortunately I cannot reproduce the problem in a minimal application (everything works fine there).

I know about WPF's common memory leak situations, and I came to the conclusion that the profiler must be wrong. So I added the following code to the problematic class:

~ProblematicChildWindow()
{
   using (StreamWriter sw = File.CreateText("d:\\garbagecollection.txt"))
   {
      sw.WriteLine(DateTime.Now.ToShortTimeString() + " garbage collected.");
   }
}

Now the strange thing is:

After opening and closing an instance of ProblematicChildWindow and forcing a garbage collection, I find a new file "garbagecollection.txt" in my D:\ folder, BUT

VS2015's memory profiler tells me that there is still an instance of ProblematicChildWindow in memory!

My question: by the fact the instance has obviously been garbage collected (because the finalizer has been called), can I be sure that the occupied memory will be released?

VS2015's memory profiler seems to have a bug in this case.

UPDATE: .NET Memory Profiler tells me that there is no instance left in memory after closing. But VS2015 does (just checked it again).

Golvellius
  • 1,928
  • 2
  • 13
  • 16
  • What happens if your force garbage collection *twice*? Specifically, `GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();`. – Damien_The_Unbeliever Jul 05 '16 at 14:52
  • 4
    Actually, when the finalizer is called, you _haven't_ been garbage collected yet. After all, if it had been, how could your object's finalizer be called? It _will_ be marked to be collected if it's still eligible, but, a finalizer can actually end up _resurrecting_ the object in question. – willaien Jul 05 '16 at 14:53
  • 1
    You might want to read Eric Lippert's blog post [When everything you know is wrong](https://ericlippert.com/2015/05/18/when-everything-you-know-is-wrong-part-one/) – juharr Jul 05 '16 at 14:54
  • @ Damien_The_Unbeliever: I get a file with one line, but the VS profiler tells me that there is still an instance in memory. – Golvellius Jul 05 '16 at 14:57
  • @ juharr: I will take a look at it, thanks. – Golvellius Jul 05 '16 at 15:11

3 Answers3

0

No, that's why we have a method like GC.WaitForPendingFinalizers:

When the garbage collector finds objects that can be reclaimed, it checks each object to determine the object's finalization requirements. If an object implements a finalizer and has not disabled finalization by calling SuppressFinalize, the object is placed in a list of objects that are marked as ready for finalization. The garbage collector calls the Finalize methods for the objects in this list and removes the entries from the list. This method blocks until all finalizers have run to completion.

The thread on which finalizers are run is unspecified, so there is no guarantee that this method will terminate. However, this thread can be interrupted by another thread while the WaitForPendingFinalizers method is in progress. For example, you can start another thread that waits for a period of time and then interrupts this thread if this thread is still suspended.

Zein Makki
  • 29,485
  • 6
  • 52
  • 63
0

Finalizer is being called by garbage collector, when it recognizes an object as unused one. However it does not guarantee, the object will be collected. It may happen if the object has references to unmanaged resources, which were not closed.

Check for resources used in that class. Some of them must be still open.

Waldemar
  • 5,363
  • 3
  • 17
  • 28
0

No. After finalize your object still can have some references to unmanaged resources. Check for inner leaks.

Mikolaytis
  • 921
  • 1
  • 12
  • 27