Circular links Cause of memory leak?

I am trying to start a memory leak in a windows forms application. I am now looking at a form containing several built-in forms. My concern is that the child forms a link to the parent form in his constructor and stores it in the private member field. Therefore, it seems to me that it's time to collect garbage:

The parent has a link to the child form through a collection of controls (the child form is embedded there). The baby is not GC'd.

The child has a link to the parent form through the private member field. The parent form is not GC'd.

Is this an accurate understanding of how the garbage collector will evaluate the situation? Any way to "prove" it for testing purposes?

+34
memory-management memory memory-leaks circular-dependency
Dec 30 '09 at 16:15
source share
6 answers

Great question!

No. Both forms will (may be) GC'd because GC does not look for links in other links directly. It searches only for what is called the "Root" link ... This includes reference variables on the stack (the variable is on the stack, the actual object is, of course, on the heap), refers to variables in the processor registers and reference variables that are static fields in classes ...

All other reference variables are accessible only (and GC'd) if they refer to the property of one of the "root" reference objects found by the above process ... (or in the object referenced by the link to the root object, etc.)

So, only if one of the forms is mentioned somewhere else in the "root" link - then both forms will be safe from GC.

The only way I can come up with to “prove” it (without using the memory tracing utilities) would be to create a couple of hundreds of thousands of these forms, in a loop inside the method, then, while in the method, look at the application’s memory, then exit the method , call GC and look at the trail again.

+36
Dec 30 '09 at 16:23
source share

As others have said, the GC has no problems with circular references. I just wanted to add that event handlers are the usual place for memory leaks in .NET. If one of your forms has an attached event handler to another object that is "live", then there is a link to your form and the form will not get GC'd.

+16
Dec 30 '09 at 16:45
source share

Garbage collection work by tracking application roots. Application roots are storage locations that contain references to objects in the managed heap (or to zero). .NET roots

  • References to global objects
  • Links to static objects
  • Links to static fields
  • Stack links for local objects
  • Stack links for object parameters passed to methods
  • Links to objects awaiting finalization
  • References in processor registers to objects in the managed heap

The list of active roots is maintained by the CLR. The garbage collector works by looking at objects in a managed heap and seeing which applications are still available, i.e. Available through the root of the application. Such an object is considered rooted.

Now suppose you have a parent form containing links to child forms, and these child forms contain links to the parent form. In addition, suppose that the application no longer contains references to the parent element or to any of the child forms. Then, for the purposes of the garbage collector, these managed objects are no longer rooted and will be garbage collected the next time the garbage collection occurs.

+13
Dec 30 '09 at 16:48
source share

If both the parent and child are not referenced, but they only refer to each other, they get a GCed.

Get a memory profiler to really test your application and answer all your questions. I can recommend http://memprofiler.com/

+5
Dec 30 '09 at 16:23
source share

I would like to reiterate Vilx's comment on events and recommend a design template that will help him decide.

Say you have a type that is the source of an event, for example:

interface IEventSource { event EventHandler SomethingHappened; } 

Here is a fragment of a class that processes events from instances of this type. The idea is that whenever you assign a new instance of a property, you first unsubscribe from any previous task, and then subscribe to the new instance. Zero checks ensure that the boundaries behave correctly, and furthermore simplify deletion: all you do is the null property.

This raises the meaning of recycling. Any class that subscribes to events must implement the IDisposable interface, as events are resource driven. (NB I skipped the correct implementation of the Dispose pattern in the example for brevity, but you get the idea.)

 class MyClass : IDisposable { IEventSource m_EventSource; public IEventSource EventSource { get { return m_EventSource; } set { if( null != m_EventSource ) { m_EventSource -= HandleSomethingHappened; } m_EventSource = value; if( null != m_EventSource ) { m_EventSource += HandleSomethingHappened; } } } public Dispose() { EventSource = null; } // ... } 
+2
Jun 24 2018-11-11T00:
source share

GC can handle circular links correctly, and if those links were the only things that supported the form, they would be compiled.
I had a lot of problems with .net without returning memory from forms. In 1.1 there were some errors caused by menuitem (I think), which meant that they were not disposed of and could leak memory. In this case, adding an explicit call to delete and clear the member variable in the form Dispose method sorted the problem. We found that it also helped restore memory for some other types of management.
I also worked with the CLR profiler for a long time, considering why forms were not collected. As far as I could tell, links were supported by frames. One on one type of form. Therefore, if you create 100 instances of Form1, then close them all, only 99 will be fixed correctly. I have not found a way to heal this. Since then, our application has moved to .net 2, and it seems a lot better. Our application memory still grows when we open the first form and do not return when it is closed, but I believe that this is due to the fact that the JIT code and additional control libraries are loaded. I also found that although the GC may deal with circular references, it seems to have problems (sometimes) with references to circular event handlers. IE object1 refers to object2 and object1 has a method that processes the event from object2 as well. I found circumstances in which this did not free objects when I was expecting, but I could never repeat it in a test case.

0
Dec 30 '09 at 16:38
source share



All Articles