Friday, January 27, 2006

Disposal and Finalization in .NET

I'm updating the material for my Industrial Strength Programming in C# and Introduzione alla Piattaforma .NET courses, adding some material on Finalization, Disposal and SafeHandle. For those not lucky enough :-))) to follow my courses, I guess the best reference available on the subject is DG Update: Dispose, Finalization, and Resource Management from Joe Duffy. There are a lot of non-trivial details about Disposal and Finalization, including the fact that during disposal you have to handle circular references by yourself (fortunately, it's pretty easy), and that if you don't suppress finalization explicitly, you'll incur some serious overhead as your objects get promoted to the next generation (for a practical and useful demonstration, see Introduction to the CLR Profiler by Peter Sollich). What's usually missing in many books and papers is why objects with a finalizer get promoted to the next generation: it would be entirely possible to finalize them during the collection process itself. The answer is pretty simple (in fact, almost simplistic): GC is meant to be fast, and finalization would slow it down. However, (hence the "simplistic") promoting objects to the next generation may force a generation 1 or 2 GC in cases where a generation 0 collection would be enough, had finalization been carried out. By careful following the Dispose(void) / Dispose(bool) pattern, we can make our classes good CLR citizens, so that the GC won't promote objects without necessity. There is still some complexity in implementing disposal right, and it's easy to make some mistake and end up with a resource leak, especially during maintenance. Well, that's what you get when you enter the garbage collected world :-).

2 comments:

Fulvio Esposito said...

Credi che implementare qualcosa di simile a quanto fatto in C++/CLI con la stessa sintassi degli oggetti automatici o in D (parola chiave auto) possa facilitare le cose o ci sarebbe sempre qualche problema? Con gli smart pointer serve un tantinello in più in progettazione, ma poi si usano che è un piacere e la memoria quasi te la scordi...

Carlo.Pescio said...

C++/CLI con gli oggetti automatici fa di tutto proprio per "forzare" regole di chiamata di Dispose (i distruttori chiamano Dispose, non sono dei finalizer). Ne parla anche Sutter nell'articolo linkato.
E' un passo avanti rispetto al C#, anche se il C++/CLI e' un baraccone che non mi piace.
Ma un po' alla volta la gente inizia a capire come stanno le cose con la garbage collection...
D'altra parte gli oggetti auto finiscono per essere (anche di nome) solo degli auto_ptr, se usciamo dal possesso esclusivo ci manca qualcosa di simile alla distruzione deterministica, e siamo di nuovo a terra...
No free lunch :-).