C#解决内存泄漏的方法有哪些
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/690071/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are ways to solve Memory Leaks in C#
提问by Jeremiah
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.
我正在学习 C#。据我所知,您必须正确设置才能让垃圾收集器实际删除所有内容。我正在寻找多年来从你那里学到的智慧,聪明人。
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!
我来自 C++ 背景并且非常习惯于代码气味和开发模式。我想了解 C# 中的代码气味是什么样的。给我建议!
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.
非常感谢。
采纳答案by Dead account
C#, the .NET Framework uses Managed Memory and everything (but allocated unmanaged resources) is garbage collected.
C#,.NET Framework 使用托管内存,所有内容(但分配的非托管资源)都被垃圾收集。
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.
可以安全地假设托管类型总是被垃圾收集。这包括arrays
,classes
和structures
。随意做int[] stuff = new int[32];
并忘记它。
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.
如果您在类中打开文件、数据库连接或任何其他非托管资源,请实现 IDisposable 接口并在您的 Dispose 方法中取消分配非托管资源。
Any class which implements IDisposable should be explicitly closed, or used in a (I think cool) Using block like;
任何实现 IDisposable 的类都应该显式关闭,或者在(我认为很酷) Using 块中使用;
using (StreamReader reader = new StreamReader("myfile.txt"))
{
... your code here
}
Here .NET will dispose reader when out of the { } scope.
这里 .NET 将在超出 { } 范围时处理 reader。
回答by user79755
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.
可能最好的方法是实现并遵循 IDisposable 模式;并在所有实现它的对象上调用 dispose 方法。
The 'using' statement is your best friend. Loosely put, it will call dispose for you on objects implementing IDisposable.
“使用”语句是您最好的朋友。松散地说,它会在实现 IDisposable 的对象上为您调用 dispose。
回答by Marc Gravell
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.
GC 的第一件事是它是非确定性的。如果您想及时清理资源,请实施IDisposable
和使用using
;它不收集托管内存,但可以对非托管资源和前向链有很大帮助。
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
- 大量固定(对 GC 可以做的事情有很多限制)
- 许多终结器(您通常不需要它们;减慢 GC)
- 静态事件 - 让大量大型对象图保持活动状态的简单方法;-p
- 廉价的长寿命对象上的事件,可以看到本应清理的昂贵对象
- “捕获的变量”意外地使图形保持活动状态
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.
为了调查内存泄漏......“SOS”是最简单的途径之一;您可以使用 SOS 查找类型的所有实例,以及可以看到它的内容等。
回答by Michael Meadows
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.
一般来说,你越少担心 C# 中的内存分配,你的情况就越好。当我遇到收集问题时,我会把它留给分析器来告诉我。
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.
您不能像在 C++ 中那样在 C# 中创建内存泄漏。垃圾收集器将永远“支持你”。您可以做的是创建对象并保存对它们的引用,即使您从未使用过它们。这是一种需要注意的代码异味。
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
- 对收集发生的频率有一些了解(出于性能原因)
- 对对象的引用不要超过你需要的时间
- 处理完实现 IDisposable 的对象后立即处理它们(使用
using
语法) - 正确实现IDisposable 接口
回答by bezieur
You can use tools like CLR profilerit 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)
你可以使用像CLR profiler这样的工具,学习如何正确使用它需要一些时间,但毕竟它是免费的。(它多次帮助我找到我的内存泄漏)
回答by Grzenio
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
保留对不再需要的对象的引用(通常在某种集合中) 因此,在这里您需要记住,您添加到集合中的所有内容也将保留在内存中。
有循环引用,例如有代表注册一个事件。因此,即使您明确未引用对象,它也无法进行垃圾回收,因为它的方法之一已注册为具有事件的委托。在这些情况下,您需要记住在丢弃引用之前删除委托。
- 与本机代码互操作并且无法释放它。即使您使用实现终结器的托管包装器,CLR 通常也不会足够快地清理它们,因为它不了解内存占用。您应该使用 using(IDisposable ){} 模式
回答by Grzenio
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.
例如:对象 A 监视对象 B 如果从 A 到 B 的引用没有被释放,则对象 B 被释放,GC 将不会正确地释放该对象。因为事件处理程序仍然被分配,GC 不会将其视为未使用的资源。
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.
有一些很棒的内存管理软件应用程序可以监控应用程序堆的情况。我发现使用 .Net Memory Profiler 有很大的好处。
HTH
HTH
回答by Konstantin Tarkus
I recommend using .NET Memory Profiler
我推荐使用.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 是一个强大的工具,用于在用 C#、VB.NET 或任何其他 .NET 语言编写的程序中查找内存泄漏和优化内存使用。
.NET Memory Profiler will help you to:
.NET Memory Profiler 将帮助您:
- 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
- 查看实时内存和资源信息
- 通过收集和比较 .NET 内存快照轻松识别内存泄漏
- 查找未正确处置的实例
- 获取有关非托管资源使用情况的详细信息
- 优化内存使用
- 调查生产代码中的内存问题
- 执行自动内存测试
- 检索有关本机内存的信息
Take a look at their video tutorials:
看看他们的视频教程:
回答by Cecil Has a Name
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.
确保对象被删除或在 .NET 行话中被垃圾收集的最佳方法是确保所有根引用(可以通过方法和对象跟踪到线程调用堆栈上的第一个方法的引用)到对象被设置为空。
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.
如果有任何根引用,GC 不能也不会收集对象,无论它是否实现 IDisposable。
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.
循环引用不会造成任何惩罚或内存泄漏的可能性,因为 GC 会在对象图中标记它访问过哪些对象。在委托或事件处理程序的情况下,忘记删除事件中对目标方法的引用可能是很常见的,因此如果事件是根,则无法收集包含目标方法的对象。
回答by Cecil Has a Name
Others have already mentioned the importance of IDisposable, and some of the things to watch out for in your code.
其他人已经提到了 IDisposable 的重要性,以及在你的代码中需要注意的一些事情。
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.
我想推荐一些额外的资源;在学习 .NET GC 的详细信息以及如何解决 .NET 应用程序中的内存问题时,我发现以下内容非常宝贵。
CLR via C#by Jeffrey Richter is an excellentbook. Worth the purchase price just for the chapter on GC and memory.
Jeffrey Richter 的CLR via C#是一本优秀的书。值得购买 GC 和内存一章的价格。
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.
该博客(由 Microsoft“ASP.NET 升级工程师”撰写)通常是我使用 WinDbg、SOS 和发现某些类型的内存泄漏的提示和技巧的首选来源。Tess 甚至设计了 .NET 调试演示/实验室,它将引导您解决常见的内存问题以及如何识别和解决它们。
Debugging Tools for Windows(WinDbg, SOS, etc)
Windows 调试工具(WinDbg、SOS 等)