As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
What are some tips I can use to avoid memory leaks in my applications? Are there any gotchas or pitfalls that I can look out for?
Call Dispose on IDisposable objects or use the using clause. That should take care of most of the leaks I can think of.
Watch that you remove any event handlers that you use. In .NET, they are the most common cause of leaked memory.
As mentioned by ocdecio be sure to call Dispose on Idisposable objects, and remember to remove event handlers when you're done with an object. When building classes that works with unmanaged resources, be sure to implement Idisposable, so the user will know that there are critical resources that'll need to be disposed of.
Also, even though garbage collections do quite a bit a work for you, you should get rid of references to objects that you're done with. Else they'll still have a root, and they won't be GC'ed.
Don't underestimate the helpfulness of tools in these situations. The .NET memory profilers are fairly mature and robust nowadays, and if you have a complicated application where an object that you think should be freed is still held as a reference by something else the ability to pinpoint that reference is invaluable.
I've just finished hunting down a memory leak where a WPF tab page hosted a Windows Form control (since these tabs held a lot of data and you could open and close them at will simply waiting until the GC cleared the memory on close was not an option). I used the YourKit profiler to take a snapshot of the memory before the tab was opened, opened a tab, closed it again and took another snapshot. Inside the profiler you could visually compare the two snapshots and see what objects had survived the process and follow their references back to the GC root. I have no experience with other profilers, but I know there are a few out there if YourKit doesn't fulfil your needs.
Edited to add:
Okay, this isn't avoiding memory leaks, it's fixing them. But I'll leave it here since I think it is useful information and I don't think that enough .NET developers know about these tools.
I know some people are going to advise garbage collection as the solution. But there are lots of cases where garbage collection doesn't give you the results that you expect. It is easy to end up holding on to a stray reference which prevents whole chains of memory from being freed. Read about how this torpedoed a DARPA Grand Challenge entry. You can argue these aren't memory leaks but if the program expects that memory to be freed it is still a problem. Just like in C programming, after a couple of months you get the hang of how to make sure you don't leave unwanted references behind.
Memory leaks are bugs, so in general - the question could be answered the same as "how to code without bugs"? In the long run - it is not possible to have no bugs, but you can limit the chance for having those in the released code.
Start with caring about developed code quality and following the guidelines mentioned by others.
Simplicity is golden - the more simple the code - the less a chance for bugs or leaks
Be careful when using unmanaged resources - Windows Handles, DB connections, GDI objects, etc.
Use using for IDisposables
Implement IDisposable for classes that carry unmanaged resources
Make sure to remove any references to unused objects - including the tricky event handlers
On top of these - implement tests to see if the memory leaks - unit, concurrency, stress and load tests could help here most. See if memory leaks by checking metrics (perf counters). You could also log object creations and destructions and analyze the logs at the end of a test.
I've ran into issues where an object (Ping) implemented Dispose() twice, by implementing the IDisposable interface and inheriting it at the same time. The inherited method did nothing, and as a result you had to cast the object to IDisposable when calling Dispose() or it would leak memory. Here's a post I wrote a few years ago with more detail.
Wrap anything which is disposable in a using construct.
Avoid COM objects.
Check to see that all event hanlders are being removed properly.
Check to see that all data bindings are being removed properly.
Keep it simple
If your application logic is getting needlessly complex, you might start ending up with memory leaks. If you keep your classes small and follow general coding practices you probably won't run into any memory leaks with managed code. It is possible, but not as likely as it use to be.
If you suspect a memory leak, use a profiler to see if any objects are being kept around longer than needed.
The last time I ran into a serious memory leak was .NET 1.1, it turned out there was a bug in the framework.
Having a basic understanding of how the garbage collector works will help you avoid abusing memory. For example, if you are keeping a reference to an object you no longer need, the gc won't be able to collect it.
Along the same lines, if you're storing data the the user enters, or data that is added over time, you should consider some kind of limitations so that your memory usage doesn't grow indefinitely.
Most memory leaks that I have encountered in .NET has been related to using COM objects and not releasing them properly. As soon as I see a reference to a COM object, I think "memory leak".
The most common case of memory not being destroyed by the GC is when you have event handlers that did not get unhooked properly. You can unhook in Dispose() if you want.
I describe the problem more in detail, and I have a way to write tests to determine if you leak the object here.
As others have said call Dispose() (or use a using statement), but additionally consider whether classes use resources and if so implement IDisposeable. This is most often the problem in my code is that I have a class with member that doesn't get cleaned up till a GC.
It's managed code, that c#, so you have to try hard to leak memory :P
Try google:
http://www.google.com/search?hl=en&client=firefox-a&rls=org.mozilla%3Aen-US%3Aofficial&hs=Mbp&q=c%23+memory+leaks&btnG=Search
Types which implement a finalizer may leak, if any one finalizer blocks for some reason. I have seen finalizers block due to locking and thread apartment issues.
As instances of types with finalizers are not collected until their respective finalizers have run a single blocking finalizer will block any other finalizable objects pending collection.
First, let me bring share my strict understanding of a memory leak. My definition of a memory leak is when you have memory you have allocated and no longer a reference to it, so it is not possible to free that memory. Having said that, it is impossible to have a memory leak in .net objects (instances of CTS types that live in the managed heap, I mean). Unreferenced memory is precisely what the GC looks for to free.
Having said that, one can have a more lax understanding of what a memory leak is. If you consider a memory leak to be a uncontrolled growth of the memory being used, well, that is very easy. Just make a big misuse of static variables, mostly ones that reference huge lists. If you keep those objects referenced, the GC will never clean them, promoting them to higher generations and making them even harder to collect. Even though this is not a memory leak in the strict sense, in the end of the day it can lead to similar symptoms. A good way to try to detect this kind of "leak" is to use the CLR Profiler.
Another source of "leaks" is through improper use of event handlers as previously stated. Every time that object A registers one of its instance methods with an event at object B, object B ends keeping an indirect reference to object A, which means that while B is alive, A will be kept alive. Please note however, that there is no circularity here. As soon as neither B or A have any root reference, no matter how many cross references they have, they will eventually be collected.
Finally, one can actually induce a memory leak in .net, but never (at least theoretically) when talking about managed memory, as the GC does an excellent job in clearing that. If any of your objects maintains a reference to unmanaged memory, for instance through interop, then that memory needs to be explicitly cleaned. Failing to do so can lead to a memory leak, indeed. Even though I've never experienced such a scenario, at least in theory this can happen. As previously stated, objects that hold such references ought to implement IDiposable in order to clear that memory and their usage should guarantee Dispose is invoked for that purpose, mainly through the usage of the using clause. Notice that Dispose will not free the object's memory, but will only ask the object to release any unmanaged memory it is referring to.
One special kind of unmanaged memory is the one needed by COM objects used in interop scenarios. These objects are accessed through Runtime Callable Wrappers, RCWs for friends, but have no Dispose. "Using" will not work. The way to release the underlying COM objects is through the static method:
System.Runtime.InteropServices.Marshal.ReleaseComObject(object);
Since "using" is only syntax sugar to call IDisposable.Dispose() in a finally block, it is not usable with RCWs, hence don't forget to place the call in ReleaseComObject(object) in a finally block yourself so you ensure it is really called.
Use "using" keyword to automatically call Dispose() method of IDisposable object.
For any COM interop you have to manually release all resources.
You may find my new article useful: How to detect and avoid memory and resources leaks in .NET applications
Related
Since C# is a managed language that performs garbage collection automatically to clean up objects etc, ...
what are the ways one can introduce a memory leak?
Are there some non-obvious ways that one should look out for?
How can you detect or look for memory leaks (once you understand how they are generated etc.)
Usually leaks show up in the form of a developer writing code that "holds on" to objects when they shouldn't be, which subsequently disallows the garbage collector from collecting on those objects.
The garbage collector is pretty good at what it does, but if you don't understand what it's doing, the likelihood of you introducing memory issues into your program is pretty high.
I would suggest reading up on the GC and understanding how it works.
Here's something to get you started:
http://www.simple-talk.com/dotnet/.net-framework/understanding-garbage-collection-in-.net/
Two.
First, building up referenced objects. Like creating objects that subscribe to an event on a form. The form is active, so can not be collected, and the event subscriptions... keep the objects alive.
Second, block the garbage colelctor in native code. Like the oracle ODP.NET driever does under certain conditions. Stops the finalizer, so any object requiring finalization WILL NOT GET IT - and thus never be released.
The obvious "memory leak" one could cause in a GC-ed language would be caused simply be retaining a reference to an object after it's needed - this is especially likely if you roll your own caching or keep other global state.
Another way would be leaking memory in unmanaged resources that weren't disposed of, although most of the standard library classes will probably dispose of those in destructors so the memory will be reclaimed sooner or later.
(I'm marking the post as CW because of the open-ended nature of the question.)
A memory leak means keeping in memory objects you don't need anymore. In C#, considering the GC collects unreferenced objects, it's equivalent to say keeping references to objects you don't need.
Think about uncorrectly scoped declarations, infinite recursion or iteration...
I have a C# application that loops through a datatable, and pushes these into some locations such as Sage and a SQL table.
While it used to work fine, I'm inexplicably now getting Out of Memory exceptions after an hour or so of running it. I've noticed in the task manager, the memory usage rises by anbout 1mb every second, and keeps on going!
I was under the impression garbage collection would take of anything, but to be sure I ensure I dispose any objects after using them. I know without code it's hard to diagnose, but there's a lot of it and I'm looking more for general advice.
but to be sure I ensure I dispose any objects after using them
Dispose() is not directly related to memory management or leaks.
You'll have to look for unused objects that are still 'reachable'. Use a memory-profiler to find out.
You can start with the free CLR-Profiler.
There are a couple of potential problems that spring to mind:
There is a large pool of objects that are left inelegible for garbage collection (i.e. they are still "reachable"). For example if you add an object to an list in every loop then the list will grown unboundedly and each element in the list will remain inelegible for garbage collection as long as that list is still reachable. I'm not claiming that this is what is happening, this is just an example of how memory might be allocated and then left without being collected.
For some reason the garbage collector isn't doing a collection.
The high memory use is actually due to an unmanaged component that you are using in your application (e.g. via P/Invoke or COM interop).
Without seeing any code its tricky to give specific advice on how to fix your problem however reading through Investigating Memory Issues should give you some pointers on how to diagnose the memory problem yourself. In particular my first step would probably be to examine performance counters to see if the garbage collector is actually running, and to check the various heap sizes.
Note that Dispose and the IDisposable interface is unrelated to memory use - its important to dispose of objects like database connections once you are done with them as it frees up any associated resources (e.g. handles) however disposing of objects that implement IDisposable is very unlikely to have an impact on memory use.
Garbage collection can only get rid of objects that are no longer referenced from anything else. In addition it can only get rid of managed objects - it has no control about memory created from native code you may be interfacing with. These therefore are the two root causes for memory leaks in C# code.
The first thing to look at is perfmon. Get the counters for the private bytes and the .net heap size for the process. If the heap size remains flat (or rises and drops) but private bytes keeps increasing you've got some native code allocating memory and not releasing it.
If the heap size just keeps growing then the leak is in your managed code and you'll need a profiler like ANTS, DotTrace or even WinDbg (with SOS extension) to inspect the heap and see what objects are lying about.
The most popular "memory leak" on .Net platform is forgotten collection that repeatetly added in some infinite loop.
When you new something for temporary memory use.
Always use following way, it ensures calling dispose.
using (Someclass A = new Someclass())
{
....something about A
}
Someclass is a class implemented interface IDisposable
GC won't save you if there some part of unsafe code is involved(P/Invoke, Com etc..), and if there still a reference some where exists.
If you find memory leaking, use WinDbg will see what is in the heap.
This article may give you some help.
http://www.codeproject.com/KB/dotnet/Memory_Leak_Detection.aspx
I guess this is very basic but since I'm learning .NET by myself, I have to ask this question.
I'm used to coding in C, where you have to free() everything. In C++/.NET, I have read about the garbage collector. From what I understand, when an instance is no longer used (in the scope of the object), it is freed by the garbage collector.
So, having that in mind, I built a little testing application. But, it seems I didn't get something because when doing the same things a few times (like, opening a form, closing it, reopening it, etc), memory leaks. And big time.
I tried to look this up on Google but I didn't find anything good for a beginner.
Is the garbage collector really freeing every objects when no longer used or there are exceptions that I have to handle? What am I missing?
Are there free tools to look up for memory leaks?
Yeah, the garbage collector is freeing your objects when they're not used anymore.
What we usually call a memory leak in .NET is more like:
You're using external resources (that are not garbage collected) and forgetting to free them. This is solved usually by implementing the IDisposable interface.
You think there aren't references to a given object but indeed there are, somewhere and you're not using them any more but the garbage collector does not know about them.
In addition, memory is only reclaimed when needed, meaning the garbage collector activates at given times and performs a collection determining them what memory can be freed and freeing it. Until it does, the memory isn't claimed so it might look like memory is being lost.
Here, I think I'll provide a more complex answer just to clarify.
First, the garbage collector runs in its own thread. You have to understand that, in order do reclaim memory the garbage collector needs to stop all other threads so that he can follow up the reference chain an determine what depends on what. That's the reason memory isn't freed right away, a garbage collector imply certain costs in performance.
Internally the garbage collector manage memory in generations. In a very simplified way there are several generations for long lived, short lived and big size objects. The garbage collector moves the object from one generation to another each time its performs a collection which happens more often for short lived generation that for long lived one. It also reallocates objects to get you the most possible contiguous space so again, performing a collection is a costly process.
If you really want to see the effects of you freeing the form (when getting out of scope and having no more reference to it) you can call GC.Collect(). Do that just for testing, it's highly unwise to call Collect except for a very few cases where you know exactly what you're doing and the implications it will have.
A little more explaining about the Dispose method of the IDispose interface.
Dispose isn't a destructor in the usual C++ way, it isn't a destructor at all. Dispose is a way to deterministically get rid of unmanaged objects. An example: Suppose you call an external COM library that happens to allocate 1GB of memory due to what it is doing. If you have no Dispose that memory will sit there, wasting space until the GC inits a collection and reclaims the unmanaged memory by calling the actual object destructor. So if you want to free the memory right away you have to call the Dispose method but you're not "forced" to do so.
If you don't use IDisposable interface then you have to free you're unmanaged resources in the Finalize method. Finalize is automatically called from the object destructor when the GC attempts to reclaim the object. So if you have a proper finalize method the unmanaged memory will get freed either way. Calling Dispose will only make it deterministic.
What leads you to conclude that there are memory leaks? Under garbage collection, there is no guarantee that memory is freed immediately, and in general the GC doesn't kick in until your process memory reaches some threshold, or the available heap has been exhausted. (The exact heuristic is complicated and not important.) So the fact that your process's memory goes up and doesn't go down doesn't necessarily mean that there's a bug. It might just be that the GC didn't get around to cleaning up your process yet.
Additionally, are you sure that there are no references to your objects? It's possible that you have references that you aren't aware of. Most memory leaks in .NET applications are because people don't realize that their memory is still being referenced somewhere.
Task Manager is a terrible way to examine your memory usage. If you want to study how the garbage collector works, install the CLR Profiler and use it to analyze your application. It will tell you exactly what the garbage collector is doing.
See How To: Use CLR Profiler.
I'm adding this as an answer rather than a comment on the question, but this follows-up a question asked by the OP in a comment:
using statement on MSDN.
IDisposable interface on MSDN.
Here is the crux of the issue: what you're used to as far as object destructors is gone. Everything you've been told about how to code correctly is screaming up from your subconscious, saying this can't be true, and if it is true, it's wrong and terrible. It's very different; it's hard to remember how much I really despised it at first (I was a proud C++ developer).
I personally promise you: it's going to be OK!
Here's another good thing to read:
Destructors and Finalizers in Visual C++.
The GC will not necessarily actually free things at the moment the object is no longer referenced. The GC will collect it at some time in the future - you don't know exactly when, but if memory is needed, the GC will perform a collection if necessary.
If you just want to figure out if you have a memory leak or not, have a look at perfmon which ships with your copy of windows:
In particular the .NET CLR Memory counter bytes in all heaps, if this number is steadily growing you have a leak.
You can even dig deeper by comparing the Gen 2 heap size to the Large Object Heap Size. If the former is growing steadily you have a large blobs of data leaking.
Once you confirm there is a leak, you can attach with windbg and use the sos extensions to determine what is leaking.
If you can afford to spend a few bucks have a look at the .NET Memory Profiler.
There are free tools available to look at the managed heap in .Net, using the SOSEX extensions to WinDBG and SOS, it is possible to run a program, pause it, then look at which objects exist on the stack and (more importantly) which other objects are holding references to them (roots) which will be preventing the the GC from collecting them.
I need to dispose of an object so it can release everything it owns, but it doesn't implement the IDisposable so I can't use it in a using block. How can I make the garbage collector collect it?
You can force a collection with GC.Collect(). Be very careful using this, since a full collection can take some time. The best-practice is to just let the GC determine when the best time to collect is.
Does the object contain unmanaged resources but does not implement IDisposable? If so, it's a bug.
If it doesn't, it shouldn't matter if it gets released right away, the garbage collector should do the right thing.
If it "owns" anything other than memory, you need to fix the object to use IDisposable. If it's not an object you control this is something worth picking a different vendor over, because it speaks to the core of how well your vendor really understands .Net.
If it does just own memory, even a lot of it, all you have to do is make sure the object goes out of scope. Don't call GC.Collect() — it's one of those things that if you have to ask, you shouldn't do it.
You can't perform garbage collection on a single object. You could request a garbage collection by calling GC.Collect() but this will effect all objects subject to cleanup. It is also highly discouraged as it can have a negative effect on the performance of later collections.
Also, calling Dispose on an object does not clean up it's memory. It only allows the object to remove references to unmanaged resources. For example, calling Dispose on a StreamWriter closes the stream and releases the Windows file handle. The memory for the object on the managed heap does not get reclaimed until a subsequent garbage collection.
Chris Sells also discussed this on .NET Rocks. I think it was during his first appearance but the subject might have been revisited in later interviews.
http://www.dotnetrocks.com/default.aspx?showNum=10
This article by Francesco Balena is also a good reference:
When and How to Use Dispose and Finalize in C#
http://www.devx.com/dotnet/Article/33167/0/page/1
Garbage collection in .NET is non deterministic, meaning you can't really control when it happens. You can suggest, but that doesn't mean it will listen.
Tells us a little bit more about the object and why you want to do this. We can make some suggestions based off of that. Code always helps. And depending on the object, there might be a Close method or something similar. Maybe the useage is to call that. If there is no Close or Dispose type of method, you probably don't want to rely on that object, as you will probably get memory leaks if in fact it does contain resourses which will need to be released.
If the object goes out of scope and it have no external references it will be collected rather fast (likely on the next collection).
BEWARE: of f ra gm enta tion in many cases, GC.Collect() or some IDisposal is not very helpful, especially for large objects (LOH is for objects ~80kb+, performs no compaction and is subject to high levels of fragmentation for many common use cases) which will then lead to out of memory (OOM) issues even with potentially hundreds of MB free. As time marches on, things get bigger, though perhaps not this size (80 something kb) for LOH relegated objects, high degrees of parallelism exasperates this issue due simply due to more objects in less time (and likely varying in size) being instantiated/released.
Array’s are the usual suspects for this problem (it’s also often hard to identify due to non-specific exceptions and assertions from the runtime, something like “high % of large object heap fragmentation” would be swell), the prognosis for code suffering from this problem is to implement an aggressive re-use strategy.
A class in Systems.Collections.Concurrent.ObjectPool from the parallel extensions beta1 samples helps (unfortunately there is not a simple ubiquitous pattern which I have seen, like maybe some attached property/extension methods?), it is simple enough to drop in or re-implement for most projects, you assign a generator Func<> and use Get/Put helper methods to re-use your previous object’s and forgo usual garbage collection. It is usually sufficient to focus on array’s and not the individual array elements.
It would be nice if .NET 4 updated all of the .ToArray() methods everywhere to include .ToArray(T target).
Getting the hang of using SOS/windbg (.loadby sos mscoreei for CLRv4) to analyze this class of issue can help. Thinking about it, the current garbage collection system is more like garbage re-cycling (using the same physical memory again), ObjectPool is analogous to garbage re-using. If anybody remembers the 3 R’s, reducing your memory use is a good idea too, for performance sakes ;)
I'm learning C#. From what I know, you have to set things up correctly to have the garbage collector actually delete everything as it should be. I'm looking for wisdom learned over the years from you, the intelligent.
I'm coming from a C++ background and am VERY used to code-smells and development patterns. I want to learn what code-smells are like in C#. Give me advice!
What are the best ways to get things deleted?
How can you figure out when you have "memory leaks"?
Edit: I am trying to develop a punch-list of "stuff to always do for memory management"
Thanks, so much.
C#, the .NET Framework uses Managed Memory and everything (but allocated unmanaged resources) is garbage collected.
It is safe to assume that managed types are always garbage collected. That includes arrays, classes and structures. Feel free to do int[] stuff = new int[32]; and forget about it.
If you open a file, database connection, or any other unmanaged resource in a class, implement the IDisposable interface and in your Dispose method de-allocate the unmanaged resource.
Any class which implements IDisposable should be explicitly closed, or used in a (I think cool) Using block like;
using (StreamReader reader = new StreamReader("myfile.txt"))
{
... your code here
}
Here .NET will dispose reader when out of the { } scope.
The first thing with GC is that it is non-deterministic; if you want a resource cleaned up promptly, implement IDisposable and use using; that doesn't collect the managed memory, but can help a lot with unmanaged resources and onward chains.
In particular, things to watch out for:
lots of pinning (places a lot of restrictions on what the GC can do)
lots of finalizers (you don't usually need them; slows down GC)
static events - easy way to keep a lot of large object graphs alive ;-p
events on an inexpensive long-life object, that can see an expensive object that should have been cleaned up
"captured variables" accidentally keeping graphs alive
For investigating memory leaks... "SOS" is one of the easiest routes; you can use SOS to find all instances of a type, and what can see it, etc.
In general, the less you worry about memory allocation in C#, the better off you are. I would leave it to a profiler to tell me when I'm having issues with collection.
You can't create memory leaks in C# in the same way as you do in C++. The garbage collector will always "have your back". What you can do is create objects and hold references to them even though you never use them. That's a code smell to look out for.
Other than that:
Have some notion of how frequently collection will occur (for performance reasons)
Don't hold references to objects longer than you need
Dispose of objects that implement IDisposable as soon as you're done with them (use the using syntax)
Properly implement the IDisposable interface
The main sources of memory leaks I can think of are:
keeping references to objects you don't need any more (usually in some sort of collection) So here you need to remember that all things that you add to a collection that you have reference too will stay in memory.
Having circular references, e.g. having delegates registered with an event. So even though you explicitly don't reference an object, it can't get garbage collected because one of its methods is registered as a delegate with an event. In these cases you need to remember to remove the delegate before discarding the reference.
Interoperating with native code and failing to free it. Even if you use managed wrappers that implement finalizers, often the CLR doesn't clean them fast enough, because it doesn't understand the memory footprint. You should use the using(IDisposable ){} pattern
One other thing to consider for memory management is if you are implementing any Observer patterns and not disposing of the references correctly.
For instance:
Object A watches Object B
Object B is disposed if the reference from A to B is not disposed of property the GC will not properyly dispose of the object. Becuase the event handler is still assigned the GC doesn't see it as a non utilized resource.
If you have a small set of objects you're working with this may me irrelevant. However, if your working with thousands of objects this can cause a gradual increase in memory over the life of the application.
There are some great memory management software applications to monitor what's going on with the heap of your application. I found great benefit from utilizing .Net Memory Profiler.
HTH
I recommend using .NET Memory Profiler
.NET Memory Profiler is a powerful tool for finding memory leaks and optimizing the memory usage in programs written in C#, VB.NET or any other .NET Language.
.NET Memory Profiler will help you to:
View real-time memory and resource information
Easily identify memory leaks by collecting and comparing snapshots of .NET memory
Find instances that are not properly disposed
Get detailed information about unmanaged resource usage
Optimize memory usage
Investigate memory problems in production code
Perform automated memory testing
Retrieve information about native memory
Take a look at their video tutorials:
http://memprofiler.com/tutorials/
Others have already mentioned the importance of IDisposable, and some of the things to watch out for in your code.
I wanted to suggest some additional resources; I found the following invaluable when learning the details of .NET GC and how to trouble-shoot memory issues in .NET applications.
CLR via C# by Jeffrey Richter is an excellent book. Worth the purchase price just for the chapter on GC and memory.
This blog (by a Microsoft "ASP.NET Escalation Engineer") is often my go-to source for tips and tricks for using WinDbg, SOS, and for spotting certain types of memory leaks. Tess even designed .NET debugging demos/labs which will walk you through common memory issues and how to recognize and solve them.
Debugging Tools for Windows (WinDbg, SOS, etc)
You can use tools like CLR profiler it takes some time to learn how to use it correctly, but after all it is free. (It helped me several times to find my memory leakage)
The best way to ensure that objects get deleted, or in .NET lingo, garbage-collected, is to ensure that all root references (references that can be traced through methods and objects to the first method on a thread's call stack) to an object are set to null.
The GC cannot, and will not, collect an object if there are any rooted references to it, no matter whether it implements IDisposable or not.
Circular references impose no penalty or possibility of memory leaks, as the GC marks which objects it has visited in the object graph. In the case of delegates or eventhandlers it may be common to forget to remove the reference in an event to a target method, so that the object that contains the target method can't be collected if the event is rooted.
What are the best ways to get things deleted?
NOTE: the following works only for types containing unmanaged resources. It doesn't help with purely managed types.
Probably the best method is to implement and follow the IDisposable pattern; and call the dispose method on all objects implementing it.
The 'using' statement is your best friend. Loosely put, it will call dispose for you on objects implementing IDisposable.