Losing Your Memory

Most so-called memory leaks in .NET applications aren’t really leaks. After all, if an object has a valid reference to it within the current scope, then the object is being used, even if you didn’t intend it. The Garbage Collector will shrug and assume you need it. If your application continues to create objects that never leave the active scope, or creates a host of class global variables, or stores a large block of data in a class global collection, your profiler will show a growth in memory consumption. It certainly will look like a leak, but the programming errors are more fundamental. You can reduce the problem by setting the unused variable to Null (or Nothing in VB.NET) but the answer is really a refactoring to restrict object scopes as much as possible.

With unmanaged resources such as a file handle, window handles (HWND), database connections, or network connection, it is a different problem. These require explicit cleanup. The garbage collector doesn’t know how or when to do it. An object that encapsulates an unmanaged resource requires a public Dispose method to clean up the unmanaged resource, which has to be called when users of the object are finished with it. This can catch out the programmer who has become less used to thinking in terms of disposal of resources after use. Often, a NET object that contains references to unmanaged resources requires the use of the object’s Dispose method, via either an explicit or implicit disposal, in order to clean up these references. Any object that encapsulates an unmanaged resource must allow implicit disposal, using the Finalize method, which is a second line of defense against a leak if the programmer fails to call Dispose. This should free any external resources that the object owns and has held onto.

Calling functions in unmanaged code that return data from .NET can cause problems because it is not always clear who owns the memory and how it should be disposed. When, for example, interacting with a COM object that is passing arrays to .NET, it is important to Marshal the array onto the managed heap and dispose of the original with the Marshal.FreeCoTaskMem method.

When leaks occur in .NET applications, they can often cause more grief than in an unmanaged application. In the latter case, the programmers are alert for all dangers of failing to dispose of resources. In a .NET application, the wonderful feeling that it is all done for you can blind you to those occasional times when you need to manage memory resources explicitly.

I’d be fascinated to hear of other types of memory problem that can happen in a managed application.

Cheers,
Laila