在.NET中,我们可以通过哪些方式获得内存泄漏?
我知道两个:
未正确取消注册事件处理程序/代理.
不在Windows窗体中处理动态子控件:
例:
// Causes Leaks Label label = new Label(); this.Controls.Add(label); this.Controls.Remove(label); // Correct Code Label label = new Label(); this.Controls.Add(label); this.Controls.Remove(label); label.Dispose();
更新:想法是列出不太明显的常见陷阱(如上所述).通常的想法是,由于垃圾收集器,内存泄漏不是一个大问题.不像以前那样在C++中.
很棒的讨论人员,但让我澄清......根据定义,如果.NET中的对象没有任何引用,它将在某个时间收集垃圾.所以这不是一种诱发内存泄漏的方法.
在托管环境中,如果你有一个你不知道的任何对象的意外引用,我认为它是一个内存泄漏(因此我的问题中的两个例子).
那么,这种内存泄漏可能发生的各种可能方式是什么?
这并不会导致泄漏,它只会为GC做更多工作:
// slows GC Label label = new Label(); this.Controls.Add(label); this.Controls.Remove(label); // better Label label = new Label(); this.Controls.Add(label); this.Controls.Remove(label); label.Dispose(); // best using( Label label = new Label() ) { this.Controls.Add(label); this.Controls.Remove(label); }
在这样的托管环境中,像这样留下一次性组件就不会出现问题 - 这是管理手段的重要组成部分.
当然,你会减慢app的速度.但你不会为其他任何事情留下一团糟.
没有办法提供全面的清单...这就像问"你怎么会弄湿?"
也就是说,确保您在实现IDisposable的所有内容上调用Dispose(),并确保在任何使用任何类型的非托管资源的类型上实现IDisposable.
时不时地在你的代码库上运行类似FxCop的东西来帮助你执行这条规则 - 你会惊讶于一些一次性对象在应用程序框架中被埋没的深度.
直接设置GridControl.DataSource属性而不使用BindingSource类的实例(http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.aspx).
这导致我的应用程序泄漏,花了我很长时间才跟踪分析器,最终我找到了Microsoft回复的错误报告:http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedidID = 92260
有趣的是,在BindingSource类的文档中,Microsoft试图将其作为经过深思熟虑的合法类传递,但我认为他们只是创建它来解决有关货币管理器和绑定数据到网格控件的基本漏洞.
请注意这一点,我敢打赌,由于这个原因,绝对有大量泄漏的应用程序!
阻止终结器线程.在取消阻止终结器线程之前,不会对其他对象进行垃圾回收.因此,使用的内存量将增长和增长.
进一步阅读:http://dotnetdebug.net/2005/06/22/blocked-finalizer-thread/