Garbage Collection in .NET helps deallocate memory in object heap, and in managed code, we do not get pointers or explicit memory allocation. So is it even possible to leak memory in .NET in literal sense, that is allocate memory to a pointer and lose handle to the pointer ?
Now, in situations, where you allocate memory, and not release them back (not necessarily lose the handle), we do not have memory leak per say, but you will end up with problem of high memory usage. And when "not release them back" happens unintentionally, we do have a problem, which have very similar characteristics to a memory leak. This is one of major memory leak causes in .NET apart from assembly leaks and loader leaks.
One simple scenario, where an average .NET programmer can leak memory unintentionally, is while using the delegates, for example event handling. Let say we have class Foo, with event "SomeEvent", and we need to handle the Foo's SomeEvent in Bar class, so
Foo.SomeEvent += Bar.HandleFoosSomeEvent
Now, if we have a program that have large number of Bar instances, and you expect Garbage collector to collect the memory allocated to these instances, when they go out of scope, you will be wrong. The instances of the Bar will not be collected, up until, the Foo object goes out of scope and collected. Why ? because, for garbage collector to collect memory of an object, it should have no references, that is it should not be rooted in GC terms. But in above case, Bar object is stilled rooted/referenced in the event handler list, inside the Foo object. So in programs like this, developer should remember to remove the event subscription to allow gc to do its job, like
Foo.SomeEvent -= Bar.HandleFoosSomeEvent
Another common scenario, where it can mess with GCs operation, is implementation of Finalize method. A finalize method on an object will cause GC, to move this object to Freachable queue ( a queue for objects waiting to be finalized), where a Finalizer thread would execute the finalize method, before GC can collect the Object. Now, by just placing a empty Finalize method on a simple .NET class, you can make sure, that the object stays or survives at least one GC Collection, because, it needs to be worked by the finalizer thread before it can be collected. This itself can prove costly, by overflowing collections of GC.
Even worse, when you have some blocking statement on your finalize method, by blocking statements, i mean, closing a database connection, rolling back a transaction, file operations. a blocking call in finalize method means, your finalizer thread will be blocked, and so all the objects that are behind the object with the blocking call, needs to wait, until the finalizer comes around.
Garbage collection helps developers spend less time on memory allocation problems, and more time on actual business problem, but then a little knowledge on how GC works internally, would save a lot of debugging hours. It helps if you understand how not to get in to GCs way. I am planning to blog more on GC, as i educate myself to be a better developer.