Indirect Delegate Root

Use this forum for questions on how to use .NET Memory Profiler and how to analyse memory usage.
Post Reply
Posts: 5
Joined: Wed Apr 30, 2008 8:09 pm

Indirect Delegate Root

Post by mikej » Fri May 08, 2009 7:53 pm

I am using Memprofiler 3.5 on my application built on .NET 2.0 SP1

When I run my Winforms application within Visual Studio 2005, I start it up by going to Profiler | Start Memory Profiler

I open a dialog & perform a set of actions then do a memory snap shot and see no memory leaks

When I run my application outside of Visual Studio and attach the memory profiler to the application. Perform the exact same set of actions, take a snap shot, I see many object instances with a yellow icon where the tooltip on the icon says "Indirect Delegate Roots". I noticed that if I check the "Only show instances included in root paths" checkbox when I drill down, that there are no references.

Are these memory leaks that I must be concerned about?

My dialog loads up user controls that I have created. I will add them and remove them dynamically depending on user interactions. The user controls contain panels, toolbars, DataGridView controls that are bound to a Typed Definition Dataset.

I have tried being very careful on how I add and remove controls from the dialog, making sure I unhook all event handlers, removing objects from list controls, undo any databinding, calling dispose on my user control, and finally setting internal member variables = null.

I found that no matter how much effort I put into unhooking everything, it seemed to always leak memory if I did not explicitly call MyUserControl.Dispose(). Is this good programming practice?

The things that looked like there were delegates pointing to my instances. Specifically things like UserPreferenceChangedEVentHandlers on my DataGridViews I used within my user controls.

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Post by Andreas Suurkuusk » Tue May 12, 2009 4:06 am

When you attach to a process and then collect a snapshot, the profiler will not force a GC before the snapshot collection, and any pending finalizers will not be run. In contrast, when running under the profiler (using "Start Memory Profiler"), a snapshot collection will trigger a full GC and the profiler will wait for finalizers to be run before retrieving memory information. So in your case, you probably have instances that are waiting for finalization, and these instances hold on to other instances through "indirect delegates". Instances that are waiting for finalization are referenced by the finalizer queue, which will presented as an unidentified root (<root>) when attaching. Unless the "Only include identified roots" option is cleared, no root paths will be presented for these instances.

It is good practice to make sure that all instances are disposed properly. Normally a UserControl will be disposed when the parent is disposed, so there's usually no need to explicitly call Dispose on the control. But, if the user control has no parent (e.g. it has been removed from the Controls collection), then you need to Dispose it explicitly. Of course, if there's an event handler add/remove error in the control, and an event handler is removed in the Dispose method, then multiple calls to Dispose might affect whether a memory leak occurs or not. However, depending on multiple calls to Dispose is not a good idea. If possible, try to locate why there is a memory leak when Dispose is only callled once.

To help you with your specific DataGridView issue, I will need some more information. Can you provide some allocation stacks and root paths for the relevant instances (e.g. the DataGridView and the EventHandlers that keep it alive)?
Best regards,

Andreas Suurkuusk
SciTech Software AB

Post Reply

Who is online

Users browsing this forum: No registered users and 16 guests