Is it ever possible in a managed system to leak memory when you make sure that all handles, things that implement IDispose
are disposed?
Would there be cases where some variables are left out?
Is it ever possible in a managed system to leak memory when you make sure that all handles, things that implement IDispose
are disposed?
Would there be cases where some variables are left out?
You may find my new article useful: How to detect and avoid memory and resources leaks in .NET applications
It's a myth that you cannot leak memory in managed code. Granted, it's much harder than in unmanaged C++, but there are a million ways to do it. Static objects holding references, unnecessary references, caching, etc. If you are doing things the "right" way, many of your objects will not get garbage collected until much later than necessary, which is sort of a memory leak too in my opinion, in a practical and not theoretical way.
Fortunately, there are tools that can assist you. I use Microsoft's CLR Profiler a lot - it is not the most user friendly tool ever written but it is definitely very useful and it is free.
As others have pointed out, as long as there's not an actual bug in the memory manager, classes that don't use unmanaged resources won't leak memory.
What you see in .NET is not memory leaks, but objects that never get disposed. An object won't get disposed as long as the garbage collector can find it on the object graph. So if any living object anywhere has a reference to the object, it won't get disposed.
Event registration is a good way to make this happen. If an object registers for an event, whatever it registered with has a reference to it, and even if you eliminate every other reference to the object, until it unregisters (or the object it registered with becomes unreachable) it will stay alive.
So you have to watch out for objects that register for static events without your knowledge. A nifty feature of the
ToolStrip
, for instance, is that if you change your display theme, it will automatically redisplay in the new theme. It accomplishes this nifty feature by registering for the staticSystemEvents.UserPreferenceChanged
event. When you change your Windows theme, the event gets raised, and all of theToolStrip
objects that are listening to the event get notified that there's a new theme.Okay, so suppose you decide to throw away a
ToolStrip
on your form:You now have a
ToolStrip
that will never die. Even though it isn't on your form anymore, every time the user changes themes Windows will dutifully tell the otherwise-nonexistentToolStrip
about it. Every time the garbage collector runs, it thinks "I can't throw that object away, theUserPreferenceChanged
event is using it."That's not a memory leak. But it might as well be.
Things like this make a memory profiler invaluable. Run a memory profiler, and you'll say "that's odd, there seem to be ten thousand
ToolStrip
objects on the heap, even though there's only one on my form. How did this happen?"Oh, and in case you're wondering why some people think property setters are evil: to get a
ToolStrip
to unregister from theUserPreferenceChanged
event, set itsVisible
property tofalse
.Small functions help in avoiding "memory leaks". Because garbage collector frees local variables at the end of functions. If function is big and takes a lot of memory you yourself have to free local variables that take a lot of memory and are no longer needed. Similary global variables (arrays, lists) are also bad.
I experienced memory leaks in C# when creating images and not disposing them. Which is a little strange. People say you have to call .Dispose() on every object that has it. But documentation for graphical C# functions doesn't always mention this, for example for function GetThumbnailImage(). C# compiler should warn you about this I think.
As already mentioned the keeping references around will lead to increasing memory usage over time. An easy way to get into this situation is with events. If you had a long living object with some event that your other objects listen to, if the listeners are never removed then the event on the long lived object will keep those other instances alive long after they are no longer needed.
It's possible to have leaks if unmanaged resources do not get cleaned properly. Classes which implement IDisposable can leak.
However, regular object references do not require explicit memory management the way lower level languages do.