Click here to Skip to main content
Click here to Skip to main content

Premature .NET garbage collection, or "Dude, where's my FooBar?"

By , 29 Aug 2011
 

It would be very nice if one could ask the .NET compilers to automatically add GC.KeepAlive(this) to the end of a class' methods; IMHO, that should have been a default behavior for classes that override Finalize. Unfortunately, since that isn't possible, one should probably, as a matter of course, include GC.KeepAlive(this) to the end of any class method which overrides Finalize.

I find it in a way curious that the creators of .NET seemed to expect Finalize to be the primary means of cleaning up after objects are no longer needed, while Dispose was something of an afterthought. While there are some scenarios where proper use of Dispose would be difficult or impractical, there are so many cases where Finalize really isn't sufficient, and so many more cases where it can lead to hard-to-track bugs, that I would in many cases think it better for a class to require the use of Dispose for correct operation, than for it to attempt cleanup using Finalize (using Finalize to sound an alarm if a class isn't disposed may be a good idea, though). Among other things, if a class never attempts cleanup via Finalize, failure to Dispose will often yield consequences which are highly visible, and thus are likely to be diagnosed and fixed. By contrast, if a class overrides Finalize to perform silent cleanup in case of a missing Dispose, it's more likely that a missing Dispose will go unnoticed, and there's a significant chance that a missing KeepAlive will cause random failures. Note that a missing KeepAlive will generally not cause trouble if the user of a class properly Disposes it, since the compiler will have to keep the object around at least until the Dispose call.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

supercat9
Web Developer
Unknown
Member
Embedded systems programmer since 1994.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralI agree that it is curious that the KeepAlive call is necess...memberPhil Atkin29 Aug '11 - 0:25 
I agree that it is curious that the KeepAlive call is necessary, and it would be better if this need had been avoided - especially since the consequences of omitting it are so difficult and complex. However, I believe it is _only_ required when the method calls into managed code. As I have mentioned in an earlier comment, the using construct reduces the risk of premature finalization but does NOT eliminate it. I do not know if an explicit call to Dispose would do it.
One of the changes I made following my discovery of this problem was to add a facility to my class library to detect failure to Dispose. When enabled for the class, an instantiation would retain details of the call stack, thread ID and time. On finalization, the object would log these details, enabling the faulty code to be discovered - whereas a Dispose would be silent.
GeneralRe: KeepAlive can be required even in 100% managed code, if a co... Pinmembersupercat929 Aug '11 - 11:51 
KeepAlive can be required even in 100% managed code, if a component of an object may be used in circumstances where the compiler can tell that the object itself won't be needed any more. There are two main ways this can happen: (1) if the object overrides Finalize in such a way as to invalidate the object's components, the Finalize method may fire while those components are in use; (2) if a WeakReference exists to an object, that WeakReference might be valid before the object calls a method on one of its components, but become invalid during the execution of that method.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 29 Aug 2011
Article Copyright 2011 by supercat9
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid