Click here to monitor SSC

Laila Lotfi

.NET tools Brand Manager & Simple-Talk Editor

Losing Your Memory

Published Friday, September 11, 2009 3:10 PM

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

by Laila

Comments

 

Chris C said:

An example I have of this kind of memory leak is in an object relational mapping layer. In order to avoid having multiple objects referencing the same row the mapping retains a global dictionary of primary key/object.  When the mapping layer receives a request for an object from the database it uses the dictionary to decide whether it needs to generate a new object, or whether to return the one it has already generated.  

The problem with this, of course, is that the object will never be disposed.  As far as I can see there is no way of determining that no other code apart from the mapping dictionary is still referencing an object, so I have no way of knowing that it can be dropped from the dictionary.  In a C++ application this scenario could perhaps be handled by reference counting pattern, but I can't see how that would work in C# ... effectively I need a way of saying "ignore this reference, just tell me if you want to get rid of it" to the garbage collector for the dictionary reference to the object...

I am wondering if you've seen such a paradigm/pattern in C#?
September 14, 2009 9:54 PM
 

jccviking said:

I’m developing a fairly large Windows Mobile app within which I recently discovered (and fixed) a pretty bad memory leak.

I’m using SQL Server CE and, in an effort to reduce the overhead associated with creating result sets, I created a result set broker.  When a client object needs a result set, it asks the broker for one having the desired sort order and filter.  There are some exceptions but, in general, I only maintain one result set per table.  So, if the client asks for a result set that’s different, than the existing one, the existing one is closed, the requested one is created, and a reference is returned.

While I don’t like data binding in general, I use a number of data grids which I bind directly to the result sets.  Whenever the broker replaces a result set, it fires a “Result Set Refreshed” event to notify users of the change.  Listeners can then rebind grids or take other appropriate action.

So here’s where it gets interesting.  Each form owns lots of classes.  Because none these classes is using unmanaged resources, I figured when I closed the form, all of the owned classes would just go away.  Not true!  Any class containing a handler for the “Result Set Refreshed” was wired to the event and therfore still had a live reference despite its owner closing.  Every time I reinstantiated a form, another set of owned classes would be instantiated and the allocated memory would increase.  After enough times, I would run out of memory.

So… contrary to the teachings of some gurus, Dispose() methods aren’t just for handling unmanaged resources.  In this case, I added a Dispose() method to every class containing a “Result Set Refreshed” event handler.  Within Dispose() I simply unwired the handler and life was good again.

JCC
September 15, 2009 12:02 AM
 

adlordy said:

Chris you can use WeakReference in C# for your task. http://msdn.microsoft.com/en-us/library/system.weakreference.aspx
September 15, 2009 2:11 AM
 

rajeshgovindarajan said:

Laila,
wat r the advantages of ants profiler? cant we trace n fix the leak manually?

Rajesh,
software engineer(Dot Net),RRD-India
November 12, 2009 7:00 AM
You need to sign in to comment on this blog

About Laila

I'm working for the .NET Tools division at Red Gate. These days, I'm spending most of my time working on SmartAssembly (.NET obfuscator, error reporting and feature usage reporting tool), and I'm currently looking to speak to anyone who has used the product for its error reporting technology. My email address: editor@red-gate.com
<September 2009>
SuMoTuWeThFrSa
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
How to Kill a Company in One Step or Save it in Three
 The majority of companies that suffer a major data loss subsequently go out of business. Wesley David... Read more...

Migrating from OCS 2007 R2 to Lync: Part 4
 Having migrated the rest of our users and legacy resources across and started getting ready to... Read more...

Automated Script-generation with Powershell and SMO
 In the first of a series of articles on automating the process of building, modifying and copying SQL... Read more...

Seth Godin: Big in the IT Business
 Seth Godin has transformed our understanding of marketing in IT. He invented the concept of 'permission... Read more...

Using SQL Test Database Unit Testing with TeamCity Continuous Integration
 With database applications, the process of test and integration can be frustratingly slow because so... Read more...