What are ways to solve Memory Leaks in C#

2019-03-25 13:13发布

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.

10条回答
老娘就宠你
2楼-- · 2019-03-25 13:40

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.

查看更多
仙女界的扛把子
3楼-- · 2019-03-25 13:44

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

查看更多
虎瘦雄心在
4楼-- · 2019-03-25 13:44

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)

查看更多
一夜七次
5楼-- · 2019-03-25 13:47

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
查看更多
地球回转人心会变
6楼-- · 2019-03-25 13:56

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.

查看更多
Melony?
7楼-- · 2019-03-25 13:59

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.

查看更多
登录 后发表回答