Tracing undisposed instances

Use this forum for questions on how to use .NET Memory Profiler and how to analyse memory usage.
Post Reply
doobieferkin
Posts: 3
Joined: Tue Aug 11, 2009 4:55 pm

Tracing undisposed instances

Post by doobieferkin » Tue Aug 11, 2009 5:06 pm

I am evaluating the memory profiler. So far I have found quite a few issues that I have resolved, however I am getting lots of undisposed instances that I cannot trace. When I look at the allocation stack the instances do not appear (that I can see) to be created directly from my code. For instance:

SafePEFileHandle
WindowsFormsSynchronizationContext (??)

Do I have to get rid of ALL of these undisposed instances for my app not to leak memory...is this typical of .Net apps? In your docs you mentioned that some classes do not need to be disposed. Where is this information..I dont want to spend hours trying to trace an undisposed instances that do not need to be disposed.

I also found that the instances of the Process class still appear as undisposed event though I have called dispose on them (MS mention something about not needing this in the compact framework).

I thought the .Net framework sorted most things out but having used the profiler I am not so sure now.

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

Post by Andreas Suurkuusk » Wed Aug 12, 2009 7:01 am

An undisposed instance indicates that an instance has been collected (or at least finalized) without being properly disposed. Since the instance have been collected (and the finalizers have run), having undisposed instances do not indicate a memory or resource leak. It does however indicate that the memory or resource utilization might not be optimal (e.g. by delaying the release of a resource and causing finalization of instances).

If possible, you should try to make sure that all instances are correctly disposed. However, it's pretty common that the .NET Framework itself causes undisposed instances and there's nothing you can do about it.

The SafePEFileHandle is a wrapper class for an unmanaged resource. Failing to dispose instances of this class will keep the resource alive for an unneccessarily long time, but the finalizer will make sure that the resource is eventually released.

It's a bit more strange that you have undisposed instances of WindowsFormsSynchronizationContext. Only one instance of this class is supposed to be created for each UI thread. Disposing a WindowsFormsSynchronizationContext instance will also dispose the MarshallingControl, which might cause undesired side effects. Do you have more than one UI thread in your application? What does the allocation call stack look like for the undisposed WindowsFormsSynchronizationContext instances?

.NET Memory Profiler 3.5 will provide additional information about what the dispose methods performs for each class, giving you a better understanding of how important it is to dispose its instances.
Best regards,

Andreas Suurkuusk
SciTech Software AB

doobieferkin
Posts: 3
Joined: Tue Aug 11, 2009 4:55 pm

Undisposed instances

Post by doobieferkin » Wed Aug 12, 2009 2:36 pm

Hi Andreas,

If you create a WinForms project with a single blank form and run the profiler, then look at the Undiposed instances you get quite a few including the WindowsFormsSynchronizationContext!

In my app I have a dynamically created control that displays photographs of users and also displays a couple of fixed icons in PictureBoxes. I have been using the profiler to locate undiposed bitmap instances and I have found the following:

If you have a PictureBox (which already contains an image) before you set a new image you must call Dispose()... this reduces the number of undiposed instances listed in the profiler.

I was still getting some undiposed bitmaps (in PictureBoxes) that have been loaded directly from the parent Control's resources. After some testing I have found the following:

1. Create a Winforms app with a Form and button.
2. Add a second Form with a PictureBox containing a Bitmap.
3. Set the button of the main Form to open the second Form
4. Run the app via the profiler and click the button to open the second Form about 10 times.
5. Look at the undisposed Bitmap instances which creep up each time you open the second form!

I think this is the cause:

1. The Bitmap is loaded directly from the resource so there is no variable (in the app code) holding a reference.
2. The GC collects the short lived image reference
3. The bitmap instance then becomes undisposed.

To fix this is I added a class level field to hold a reference to the image.
In this initialize event I added this.img = PictureBox1.Image;

In the Dispose override:
if (this.img != null)
{
this.img.Dispose();
}

Run the app again through the profiler and you dont get any undisposed instances!!

The problem seems to be with images loaded from the resources. I think the same may be true for Fonts.

Using the profiler an a short time has taught me so much about the .Net framework but also makes me question what I thought I knew!

I suppose the key to using the profile is knowing what is a problems and what is not.

Hope this makes some sort of sense!!

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

Post by Andreas Suurkuusk » Wed Aug 12, 2009 9:23 pm

You are correct. Undisposed WindowsFormsSynchronizationContext instances are pretty common in a Windows forms application. They are created when the BeginInvoke method is used. Why the WindowsFormsSynchronizationContext is disposable I don't know. If a WindowsFormsSynchronizationContext is disposed, it would also dispose the marshaling control, which would prevent any subsequent call to BeginInvoke. I think this is a bug in the framework, or at least a strange design. You can just ignore the undisposed WindowsFormsSynchronizationContext instances.

Regarding the undisposed Bitmaps. Unfortunately it is not possible to avoid undisposed resources that are retrieved from the ResourceManager. From the MSDN documentation:
Performance Considerations
If you call the GetObject method multiple times with the same name parameter, do not depend on the return value being a reference to the same object. This is because the GetObject method can return a reference to an existing resource object in a cache, or can reload the resource and return a reference to a new resource object.
Since it's not possible to know whether you will receive a cached instance or a new instance, you cannot dispose it yourself. You can mitigate the problem by only retrieving the resource once from the ResourceManager, but it will make things less convenient (e.g. it will prevent you from assigning the Bitmap in the Form designer).
Best regards,

Andreas Suurkuusk
SciTech Software AB

doobieferkin
Posts: 3
Joined: Tue Aug 11, 2009 4:55 pm

Undiposed instances

Post by doobieferkin » Thu Aug 13, 2009 7:38 am

Thanks for your informative reply. I think I understand what is going on now...

One last question regarding undisposed instances. I have also been getting a large number of undisposed Fonts. Using the pofiler I have found out why.

In my app I have used the Tahoma Font for all forms and controls. As this is not the default font the designer adds a line in the designer created code to create instances of the fonts...it is these instances that become undisposed instances. If you use the default font then the number of undiposed instances is reduced considerably. I assume that the runtime will call the finalize method on these instances. Am I correct in assuming that I can ignore these?

Is there a way to tell if the finalizer has been called on these instances.

I would like to add that the Memory Profiler is an excellent product and I am wondering how I ever managed without it :D

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

Post by Andreas Suurkuusk » Thu Aug 13, 2009 3:24 pm

It's correct that a Font will become undisposed if it's assigned in the form designer. Again, this is not a serious problem, but it will have some impact on performance and resource utilization. So, you can ignore these undisposed instances.

If a finalizable instance is counted as undisposed, then the finalizer has been run (or is at least running).
Best regards,

Andreas Suurkuusk
SciTech Software AB

abhawasinka
Posts: 2
Joined: Fri Jul 19, 2013 4:08 am

Re: Tracing undisposed instances

Post by abhawasinka » Wed Jul 24, 2013 3:17 am

Ironing any handle leak is NOT correct. Every leak is caused due to some mistake in the user code or bad design.

So, what 'Andreas Suurkuusk' mentioned above to ignore the is NOT correct.

This problem is very similar to http://forum.memprofiler.com/viewtopic. ... 337&p=6645

The industry in which I work, there the deployed applications are rarely re-started. So, even 1 handle leak per day also can't be ignored. Recently, we were noticing handle leaks from our applications. During investigation we found very interesting items:

1) If you are creating a new thread and then create any WinForms or WPF based control/UI on it, there will be handle leak.
2) This is mainly caused because of the ThreadContext that is created due to
=> In WinForm => WinFormSynchronizationContext
=> In WPF => Dispatcher is created automatically, which internally forces the ThreadContext to be created.
3) Solution:
=> WPF: Simple fix is to call Dispatcher.InvokeShutdown() or follow similar approach as for WinForms mentioned below (keeping the dispatcher object)
=> WinForm:
Solution 1) Run the Message pump and add the Exit message in the message pump. OR
Solution 2) Create a single dedicated thread and use it if you want to create any UI object. To do this, on the new thread you must first create a WinForm based control which will force the creation of SynchronizationContext. Then store reference of SynchronizationContext.Current (say uiContext) in some static variable, then call Application.Run() to keep the thread running. Now, you can use uiContex.Send() to execute the code on the UI thread.
-
Regards,
Ashutosh Bhawasinka

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

Re: Tracing undisposed instances

Post by Andreas Suurkuusk » Wed Jul 24, 2013 8:30 pm

I definitely agree that you should not ignore a leaked handle. I previously worked on a project where we had a .NET application collecting data and controlling a scientific instrument on an embedded system, and the software should be able to run for months without being restarted. So I am fully aware how important it is to avoid even minor memory and resource leaks. We actually created .NET Memory Profiler in order to make sure that this program did not have any memory or resource leaks.

However, I didn't suggest that you should ignore a leaked handle. I said that you could ignore undisposed instances of the System.Drawing.Font class. An undisposed instance is not a leaked instance. It becomes marked as undisposed after the finalizer has run and the handle has been released. For the Font class, an undisposed instance will just delay the release of the handle until the finalizer runs, but the handle will eventually be released. If possible, it is always a good idea to explicitly Dispose instances that wraps native resources, but it the instances are created internally by the framework or a 3rd-party library, this is not always possible.
Best regards,

Andreas Suurkuusk
SciTech Software AB

Post Reply

Who is online

Users browsing this forum: No registered users and 30 guests