Re: StatusStrip control leaks its collection items



On Fri, 11 Jul 2008 07:49:26 -0700, <carl.clawson@xxxxxxxxxxxxx> wrote:

I agree that garbage collection is non-deterministic. No argument
there. I also agree that calling Dispose when possible is a very good
practice. It's what I normally do.

It's not just "very good practice". It's mandatory for correct code.

As an example, here's a quote from MSDN: "To provide explicit control, implement the Dispose provided by the IDisposable. The consumer of the object should call this method when it is finished using the object." And from the same page "Note that even when you provide explicit control using Dispose, you should provide implicit cleanup using the Finalize method. Finalize provides a backup to prevent resources from permanently leaking if the programmer fails to call Dispose."
http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx

They aren't saying that implementing IDisposable provides an optional approach to managing unmanaged resources. They are saying that if an object goes to the trouble of implementing IDisposable, then the user of that object is expected to call Dispose() when they're done with it, and that the finalizer exists in order to prevent incorrect code from creating permanent problems.

But I still maintain that an object that wraps an unmanaged resource
must release that resource in its finalizer. If the finalizer never
gets called, so be it. The object can't help that.

You are confusing two different issues. An object that maintains unmanaged resources must implement a finalizer, and must release those unmanaged resources in the finalizer. So you got that part correct. However, the finalizer doesn't exist for correct code. It exists for incorrect code. That is, it's a backup plan for dealing with code that is buggy.

In a bug-free program, a finalizer of an object implementing IDisposable is never called.

Now back to the problem at hand, I am finding that controls removed
from the StatusStrip appear to either A) never get finalized, which
means a reference to them is probably being held somewhere because
other deleted controls ARE getting finalized,

Without a complete program there is no way to know for sure why your controls aren't getting finalized. But that's not relevant. The fact is, your own code has absolutely no business _relying_ on finalization. You _must_ dispose the controls yourself if you expect your code to work correctly and reliably.

Now, you may in fact find that even if you call Dispose(), you still have a bug somewhere. For example, if the controls are actually still being referenced somewhere else, and something tries to access them after they're disposed, an exception will probably be thrown.

But at least you'll know that the code that thinks it's cleaning up the controls is disposing them properly.

In fact, if anything this illustrates why relying on the non-deterministic behavior of finalization is such a bad idea. It pushes other bugs farther out, making them harder to find and fix.

Pete
.



Relevant Pages

  • Re: Need explanation on calling Close() from finalizer.
    ... understand is why .NET classes cannot clean up their unmanaged resources ... > NET's Garbage Collector, like you've stated, automated memory management, ... > the Dispose pattern. ... >>> hoping your finalizer will someday be called when the garbage collector ...
    (microsoft.public.dotnet.framework.adonet)
  • Re: Clean Up managed resources
    ... these have unmanaged resources. ... If somebody called Dispose on your object, ... If the finalizer is called on your object, ... threads while it determines reachability from all the different roots. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Disposing of brushes
    ... fonts etc take GDI handles - and you could run short of those ... unmanaged resources, the number one reason to have IDisposable? ... in this special case the finalizer will call Disposefor you, ... Dispose() in the finalizer and supress the finalizer if Dispose is ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: About speed
    ... IDisposable needs a finalizer, and most code that I see that implements ... void IDisposable.Dispose ... call GC.SupressFinalizer inside their Dispose method. ... then disposed explicitly (using IDispose), ...
    (borland.public.delphi.non-technical)
  • RE: newbie: implementing destructors
    ... finalizer to your class means it takes longer to garbage collect (look up on ... have some 3rd party DLL which internally allocates a chunk of memory, ... environment is not aware of this memory so at no point will it clean up this ... let's call it Dispose for now which you can call ...
    (microsoft.public.dotnet.languages.csharp)