views:

358

answers:

9

What do you keep on mind to avoid memory leaks when you write thousands lines of .NET code? I'm a big fan of prevention over inspection , there is a famous example regarding this point which is using a "StringBuilder" to combine strings instead of "String1+String2", so what is else out there from your coding experience?

thanks in advance for sharing your thoughts.

+1  A: 

Every DataTable.NewRow() must have a matching DaraTable.Rows.Add(...).

Ovidiu Pacurar
+5  A: 

Make sure you always dispose IDisposable objects. Furthermore, try to always use "using (...)" blocks to declare disposable objects.

Ty
+6  A: 

set root references to null after use.

More info here: If we forget to null out rooted references, the GC is prevented from efficiently freeing memory as quickly as possible, resulting in a larger memory footprint for the application. The problem can be subtle, such as a method that creates a large graph of temporary objects before making a remote call like a database query or call to a Web service. If a garbage collection happens during the remote call, the entire graph is marked reachable and is not collected. This becomes even more costly because objects surviving a collection are promoted to the next generation, which can lead to a midlife crisis.

Gulzar
Setting variables to null is rarely useful and clutters up code. In particular, when a local variable is no longer used in the rest of a method, it won't be considered as a root in release mode. Usually instance variables are useful as long as the object itself is rooted.
Jon Skeet
(Continued) Static variables tend to be relevant for the entire life of the AppDomain (e.g. for a cache or factory). I very, very rarely set a variable to null for the sake of the GC.
Jon Skeet
i agree we should not clutter code and it does not work in all cases. but this was one place which hit us and thought I will share.
Gulzar
Jon - like you said in your post, ultimately it depends on the situation. most of the answers posted here (mine included) might not be relevant anyway esp with the GC getting more and more optimized..
Gulzar
I'm just wary of advice which is unqualified (i.e. doesn't say where it can be useful) and *usually* does more harm than good (i.e. no help, but hurts readability)
Jon Skeet
+3  A: 

Be aware of the complexity of everything you do, as far as possible, and think about each situation instead of relying on dogma. For instance, also be aware that using a StringBuilder isn't always the right way to join strings :)

Where possible, try to stream data rather than buffering it - you need to be careful here when it comes to LINQ to Objects, understanding which operators buffer and which stream (and which do both with different sequences).

(Neither of these are really memory "leaks" as such - but I'm thinking about places where you can rapidly use more memory than you expect to.)

Jon Skeet
Jon, do you have any good references on the latter half of your post, regarding Buffering Vs. Streamiung of data in LINQ. Sounds like it should be required reading but its not something I've stumbled so far.
Eoin Campbell
Jon Skeet
Cheers, I've added that to "To Buy" book list in the office.
Eoin Campbell
LOL - I wouldn't do it just on my say so. I'm biased :) And heck, it might not even give the details for all of the operators - I can't easily check right now. If it doesn't, please feel very free to complain...
Jon Skeet
i grabbed a copy of your book from the local library last week. good read so far. Thanks!!
Gulzar
+9  A: 

Events. Always unsubscribe from events, this is single most leak-providing feature of .NET.

Subscribing to event means "notify and hold me while you are alive", not "notify me while I'm alive". Failing to unsubscribe from event usually leads to large clusters of hanging objects, especially in UI.

Ilya Ryzhenkov
This is only relevant if you expect the event publisher to last for longer than you do. In those cases it can indeed be a killer, but I don't think it happens often enough to warrant an "always" - particularly as that implies making your class disposable, which can make life trickier elsewhere.
Jon Skeet
Well, we are talking "watch list", and also I edited answer a bit :)
Ilya Ryzhenkov
+1  A: 
something.someEvent += new EventHandler(memoryhog.someMethod);
[...]
something.someEvent += new EventHandler(memoryhog.someMethod);
[...]
something.someEvent -= new EventHandler(memoryhog.someMethod);

If you miss unhooking all the event handlers from an object then the object that implements the event handler will stick around in memory for the lifetime of the object with the event.

The Managed DirectX library had a bug like this, which would cause large memory leaks.

Cameron MacFarland
Covered by Ilya's response about "events". Please delete.
Sunny
Both answers were added within seconds of each other. My answer is not wrong, so I won't delete it.
Cameron MacFarland
+1  A: 

Specific to .NET Compact Framework: you have to dispose all graphics related objects (Graphics, Pen, SolidBrush, Bitmap) explicitly or otherwise they will hang around in memory (not great when you're working with low-memory devices).

Covered by Ty's response about "using()". Please delete.
Sunny
worth mentioning explicitly, please dont delete
Steven A. Lowe
I agree with Steven
egapotz
+2  A: 

Not exactly a memory leak, but the one thing that alwas gets me:

Always Close your SQL connections after using them.

BoltBait
+1  A: 

If using COM interop, use Marshal.ReleaseComObject after you are done with the COM object to release the Runtime Callable Wrapper (RCW).

Also, if your COM object has a property or method which returns another COM object, take care to always assign it to a variable and release it afterwards.

I.e. this will leak the object received by GetFirstChild:

string name = myBigComObject.GetFirstChild().Name;

Use istead:

ChildComObject firstChild = myBigComObject.GetFirstChild()
string name = firstChild.Name;
Marshal.ReleaseComObject(firstChild);
Sunny