Memory-Leak when not calling frm.Dispose() after the form was closed?

R

Roberto Rocco

Hello all,

We've got the following severe and very strange problem:

We open a modal form with ShowDialog() containing nothing but a PictureBox with an image of approx. 500 kB.
The code looks like this:

FormTest frm = new FormTest();
frm.ShowDialog();

Then we manually close the form with this.close (inside the form).
After the form has been closed we always log the physical memory on the device.

Then we show the form again, close it again, and so on...

What we notice is that the physical memory decreases each time the form is shown and that memory is not released after the form has been closed.
This happens a couple of times since finally an out of memory error occurs!
So the garbage collector obviously did not manage to clear the resources.


If we make a Dispose() call instead after the form has been closed, then the memory gets freed from time to time and it never comes to a point where an out of memory error occurs.
So this way the garbage collector obiously manages to free the resources.

Now what does this mean??

According to MSDN it says: "When a form is closed, all resources created within the object are closed and the form is disposed"
So from my understanding that means that closing a form implicitly calls Dispose() on the form, or does it not??

If not - and that's what we experience - then one would have to make a Dispose() call every time a form has been closed, as so:

FormTest frm = new FormTest();
frm.ShowDialog();
frm.Dispose();

Or, alternatively use the using-statement (but due to a bug in CF 1.0 you have to add IDisposable to the form definition manually!).

Is this really the correct behaviour?
Is the caller of a form really required to call Dispose() manually?

If of any interest I can supply a little Test Application that proofs this behaviour.

Many thanks in advance for every enlightment on this. :)

Best regards,

Roberto Rocco.
 
A

Alex Feinman [MVP]

The garbage collector will not do anything until your managed memory will grow to a certain amount (750KB). The Picture box image is a bitmap and those 500KB (actually more than that uncompressed) use unmanaged (GDI) memory. Multiple copies of your form wil ltake very little of managed memory and GC will ignore it for a while, but you will run out of unmanaged memory.

The proper way to handle it is indeed to dispose of the form explicitly as in your example. This is not a bug - it's a feature that was a result of a certain trade-off.

--
Alex Feinman
---
Visit http://www.opennetcf.org
Hello all,

We've got the following severe and very strange problem:

We open a modal form with ShowDialog() containing nothing but a PictureBox with an image of approx. 500 kB.
The code looks like this:

FormTest frm = new FormTest();
frm.ShowDialog();

Then we manually close the form with this.close (inside the form).
After the form has been closed we always log the physical memory on the device.

Then we show the form again, close it again, and so on...

What we notice is that the physical memory decreases each time the form is shown and that memory is not released after the form has been closed.
This happens a couple of times since finally an out of memory error occurs!
So the garbage collector obviously did not manage to clear the resources.


If we make a Dispose() call instead after the form has been closed, then the memory gets freed from time to time and it never comes to a point where an out of memory error occurs.
So this way the garbage collector obiously manages to free the resources.

Now what does this mean??

According to MSDN it says: "When a form is closed, all resources created within the object are closed and the form is disposed"
So from my understanding that means that closing a form implicitly calls Dispose() on the form, or does it not??

If not - and that's what we experience - then one would have to make a Dispose() call every time a form has been closed, as so:

FormTest frm = new FormTest();
frm.ShowDialog();
frm.Dispose();

Or, alternatively use the using-statement (but due to a bug in CF 1.0 you have to add IDisposable to the form definition manually!).

Is this really the correct behaviour?
Is the caller of a form really required to call Dispose() manually?

If of any interest I can supply a little Test Application that proofs this behaviour.

Many thanks in advance for every enlightment on this. :)

Best regards,

Roberto Rocco.
 
R

Roberto Rocco

Hello Alex,

thank you for your fast reply.
Ok, I now understand that - despite what MSDN says about the Close() method - the resources of the form are *not* automatically freed when the form is closed via this.Close().

Now just to make some points clear that were discussed here in the forum often in oppositional ways:

1.)
Are all the controls of the form automatically disposed when the Dispose() method of the form is called, or do I need to dispose them separately?
Or maybe better said: Is the Dispose() method of each control of the form automatically called when the Dispose() method of the form is called?
On some postings here I could find that there is (was?) a bug where the forms are (were?) missing to call Dispose() for their hosted controls.

In my concrete example: Do I have to call the Dispose() method for my PictureBox myself or ist it done automatically when the Dispose() method of the form is called?
(Of course I understand that unmanaged resources that are not controls have to be disposed by myself!)

2.)
If I want to dispose the form, is it absolutely necessary to do it from "outside" the form like this:

MyForm frm = new MyForm();
frm.ShowDialog();
frm.Dispose();

or can it be done inside the form?
I already tried to call this.Dispose() from the MyForm_Closed() event, but I'm getting the following error message:

"An unhandled exception of type 'System.ObjectDisposedException' occurred in System.Windows.Forms.dll"

(I'm using CF 1.0 SP3)
Is there a better place to call Dispose() or is it simply not possible to do it from within the form?

3.)
If the Garbage Collector doesn't do anything until memory isn't lower than 750k, what happens then in case a big memory block is required at once?
Say: Currently we have 1000k physical memory left and there's 5000k of disposed (but not yet freed!) memory. And now a 2000k memory block is required.
Will this lead to an out of memory error? (I fear so, since that is what we're experiencing)


Whew, a lot of questions, I' sorry.
But it looks to me as if that is a very important design decision whether to reuse a modal form or to rebuild it creating it again with new.
This is especially true when you have to handle many forms where reusing them all means to hold them all in memory.
Therefore I tend to *really* close a form and dispose everything it used.
But to do properly I need to fully understand how the framework handles those things.

Many thanks for your suggestions.

Roberto Rocco.




The garbage collector will not do anything until your managed memory will grow to a certain amount (750KB). The Picture box image is a bitmap and those 500KB (actually more than that uncompressed) use unmanaged (GDI) memory. Multiple copies of your form wil ltake very little of managed memory and GC will ignore it for a while, but you will run out of unmanaged memory.

The proper way to handle it is indeed to dispose of the form explicitly as in your example. This is not a bug - it's a feature that was a result of a certain trade-off.

--
Alex Feinman
---
Visit http://www.opennetcf.org
Hello all,

We've got the following severe and very strange problem:

We open a modal form with ShowDialog() containing nothing but a PictureBox with an image of approx. 500 kB.
The code looks like this:

FormTest frm = new FormTest();
frm.ShowDialog();

Then we manually close the form with this.close (inside the form).
After the form has been closed we always log the physical memory on the device.

Then we show the form again, close it again, and so on...

What we notice is that the physical memory decreases each time the form is shown and that memory is not released after the form has been closed.
This happens a couple of times since finally an out of memory error occurs!
So the garbage collector obviously did not manage to clear the resources.


If we make a Dispose() call instead after the form has been closed, then the memory gets freed from time to time and it never comes to a point where an out of memory error occurs.
So this way the garbage collector obiously manages to free the resources.

Now what does this mean??

According to MSDN it says: "When a form is closed, all resources created within the object are closed and the form is disposed"
So from my understanding that means that closing a form implicitly calls Dispose() on the form, or does it not??

If not - and that's what we experience - then one would have to make a Dispose() call every time a form has been closed, as so:

FormTest frm = new FormTest();
frm.ShowDialog();
frm.Dispose();

Or, alternatively use the using-statement (but due to a bug in CF 1.0 you have to add IDisposable to the form definition manually!).

Is this really the correct behaviour?
Is the caller of a form really required to call Dispose() manually?

If of any interest I can supply a little Test Application that proofs this behaviour.

Many thanks in advance for every enlightment on this. :)

Best regards,

Roberto Rocco.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top