在.NET观点:
- 什么是内存泄漏 ?
- 如何确定是否您的应用程序泄漏? 带来哪些影响?
- 如何防止内存泄漏?
- 如果您的应用程序有内存泄漏,它消失在进程退出或被杀? 还是你在你的应用程序的内存泄漏的影响,即使过程完成后,系统上的其他进程?
- 并且怎么样通过COM互操作和/或P访问非托管代码/调用?
在.NET观点:
我见过的最好的解释是在免费的第7章编程电子书的基础 。
基本上,在.NET时引用的对象扎根,因此不能被垃圾收集发生内存泄漏。 当你持有到超出预期的范围引用此意外发生。
你会知道你有泄漏,当你开始OutOfMemoryExceptions或你的内存使用量上升超过你所期望( 性能监视器具有良好的内存计数器)。
理解.NET的内存模型是避免它的最好方式。 具体来说,了解垃圾收集器是如何工作的,以及如何引用工作 - 再次,我是指你的电子书的第7章。 另外,还要留意常见的陷阱,可能是最常见的事件。 如果对象A注册到对象B上的一个事件,然后一个对象,直到对象B消失,因为B就掌握所涉及的引用将坚持围绕。 解决的办法是,当你完成注销您的活动。
当然,美好的记忆曲线将让你看到你的对象图,探索你的对象的嵌套/参照,看看引用来自何方,什么根对象负责( 红色门蚂蚁配置文件 ,JetBrains公司dotMemory, memprofiler确实不错选择,或者您可以使用纯文本的WinDbg和SOS,但我强烈建议商业/视频产品,除非你是一个真正的大师)。
我相信非托管代码是受其典型的内存泄漏,除了共享引用是由垃圾收集管理。 我可能是错的最后一点。
严格地说,内存泄漏会消耗存储器即“不再使用”由该程序。
“不再使用”有一个以上的意义,它可能意味着“没有更多的参考吧”,就是完全不可恢复的,或者它可能意味着,引用,收回,未使用的,但该程序保持无论如何参考。 只有后来适用于.NET带来近乎完美的管理对象 。 然而,并不是所有的类都是完美的,在某些时候一个潜在的非托管的实施可以为这一过程永久泄漏资源。
在所有情况下,应用程序消耗更多的内存比严格要求。 双方的影响,根据泄露的ammount的,可从没有去,引起过度收集放缓,到系列内存例外,最后一个致命的错误,然后强制进程终止。
你知道一个应用程序有内存问题时监测显示,越来越多的内存是每个垃圾收集周期之后分配给你的进程。 在这种情况下,你要么保持太多的记忆,或一些潜在的非托管实现泄漏。
对于大多数泄漏,当过程结束资源恢复,但有些资源并不总是在一些精确的情况下恢复,GDI的光标句柄是臭名昭著的那个。 当然,如果你有一个进程间通信机制,在其他进程分配的内存不会被释放,直到该进程释放,或终止。
我认为,“什么是内存泄漏”和“带来哪些影响”的问题已经被回答得很好,但我想在其他问题补充一些更多的东西......
如何理解是否您的应用程序泄漏
一个有趣的方法是打开性能监视器 ,并在所有堆和#第二代集合添加痕迹的字节数 ,在每种情况下就在你的进程看。 如果行使特定功能会导致总字节数增加,该内存仍然在未来的Gen 2收集后分配的,你可能会说该功能泄漏内存。
如何预防
其他很好的意见已获得。 我只想补充一点,也许是.NET的内存泄漏的最普遍被忽视的原因是事件处理程序添加到对象,而不删除它们。 连接到对象的事件处理程序的参考对该对象的形式,这样可以防止收集即使所有其他引用都没有了。 应注意将分离的事件处理程序(使用-=
在C#语法)。
是否泄漏消失进程退出,和什么有关COM互操作的时候?
当你的进程退出,映射到其地址空间中的所有内存由OS回收,包括任何COM对象的DLL从供应。 相对而言很少,COM对象可以从独立的进程提供服务。 在这种情况下,当你的进程退出,你仍可能负责在您使用的任何COM服务器进程分配的内存。
如果你需要诊断.NET内存泄漏,检查这些链接:
http://msdn.microsoft.com/en-us/magazine/cc163833.aspx
http://msdn.microsoft.com/en-us/magazine/cc164138.aspx
这些文章描述了如何创建进程的内存转储以及如何分析它,这样你可以先确定您的泄漏是管理或管理的,如果它是管理,如何找出它的来源。
微软也有帮助生成崩溃转储,以取代ADPlus的,称为DebugDiag资料较新的工具。
http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en
我将定义的内存泄漏的对象不释放它完成后分配的所有内存。 我发现这个可以,如果你使用的是Windows API和COM(即有一个错误的,或没有被正确的管理,即非托管代码),在架构和第三方组件在应用程序中发生。 我还发现没有使用像钢笔某些对象可能会导致问题后共度了。
我个人遭受了内存不足异常可引起,但不是唯一的以点.NET应用程序的内存泄漏。 (OOM也可以来自钉扎见钢钉ARTICAL )。 如果你没有得到OOM错误或需要确认它是否是内存泄漏引起那么它的唯一方法是分析您的应用程序。
我也想尝试,并确保以下几点:
a)在实现IDisposable一切都被设置或者使用finally块或使用这些语句包括刷子,笔等(有些人认为设置一切,没有什么附加)
二)任何有密切的方法是使用终于再次关闭或使用using语句(虽然我一直在使用并不总是紧密依赖发现,如果你声明的using语句外的物体)
c)如果您正在使用非托管代码/ Windows的API的,这些都是正确的后处理。 (有些人清理方法来释放资源)
希望这可以帮助。
从微软CLR使用探查http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en是一个伟大的方式来确定哪些对象持有的内存,什么执行流程线索创造这些对象,并且也监测这其中在堆(碎片,LOH等)对象活。
的垃圾收集器是如何工作的,最好的解释是杰夫Richters 通过C#CLR书,(CH。20)。 读这给出了一个伟大的接地理解对象如何坚持。
一个意外生根对象最常见的原因是挂钩事件outisde类。 如果挂钩的外部事件
如
SomeExternalClass.Changed += new EventHandler(HandleIt);
忘记当你处理,然后SomeExternalClass有裁判你的类解开它。
如上面提到的, 赛特内存分析器是优异的在显示您怀疑被泄漏对象的根。
但也有一个非常快速的方法来检查特定类型的只是使用WnDBG(连接时,你甚至可以在VS.NET立即窗口中使用此):
.loadby sos mscorwks
!dumpheap -stat -type <TypeName>
现在这样做,你认为会处理该类型的对象(如关闭一个窗口)的东西。 它的方便这里有一个调试按钮的地方,将运行System.GC.Collect()
几次。
然后运行!dumpheap -stat -type <TypeName>
试。 如果号码不下去了,还是没下去你想象得那么多,那么你有一个进一步调查的基础。 (我从给出的研讨会这个技巧英戈夯 )。
我想在托管环境中,一泄漏是你保持一个不必要的参考一大块内存左右。
为什么人们认为,在.NET中的内存泄漏是不一样的其他任何泄漏?
内存泄漏是当您连接到一个资源,不要让他走了。 你既可以在托管和非托管代码做到这一点。
关于.NET和其他编程工具,有过关于垃圾收集的想法,并尽量减少的情况,这将使您的应用程序泄漏的其他方式。 但是,防止内存泄漏的最佳方法是,你需要了解你的基本的内存模型,以及事情是如何工作的,在平台上所使用。
相信GC和其他魔术将清理你的烂摊子是一小段路内存泄漏,并将于以后难以找到。
当编码非托管,您通常一定要清理,你知道你拿的保留的资源,将是你的责任,清理,而不是看门的。
在另一方面.NET,很多人认为,GC将清理一切。 那么,它一定给你,但你必须确保它是如此。 .NET不换很多东西,所以你并不一定知道,如果你正在处理一个管理或托管资源,你需要确保你正在处理什么用。 处理字体,GDI资源,活动目录,数据库等通常是你需要看出来的东西。
在管理方面,我会放就行了我的脖子说它不走,一旦进程被杀死/删除。
我看到很多人都有这样的,虽然,我真的希望这将结束。 你不能要求用户终止您的应用程序来清理你的烂摊子! 看看浏览器,可以被IE,FF等,然后打开,说,谷歌阅读器,让它继续存在一些天,看看会发生什么。
如果你再打开浏览器,冲浪到一些网站的另一个选项卡,然后关闭托管了由浏览器泄漏其他页面的标签,你认为浏览器将释放内存? 不是这样的IE浏览器。 在我的电脑IE就会随便吃内存1吉布在短时间内(约3-4天),如果我用谷歌阅读器。 有些newspages是雪上加霜。
我想在托管环境中,一泄漏是你保持一个不必要的参考一大块内存左右。
绝对。 另外,不使用.Dispose()方法在一次性物品适当时可引起MEM泄漏。 做到这一点的最简单的方法是用一个使用块,因为其自动地在端部执行.Dispose():
StreamReader sr;
using(sr = new StreamReader("somefile.txt"))
{
//do some stuff
}
如果你创建一个使用非托管对象的一类,如果你没有正确地实现了IDisposable,你可能会导致内存泄漏你的类的用户。
所有的内存泄漏是由程序终止解决。
泄漏足够的内存和操作系统可能会决定代表您解决这个问题。
我会在.NET什么MEM泄漏将与伯纳德同意为。
你可以分析您的应用程序,看看它的内存使用,并确定如果管理大量内存时,它不应该是你会说这有泄漏。
在管理方面,我会放就行了我的脖子说它不走,一旦进程被杀死/删除。
非托管代码是它自己的野兽,如果泄漏在它存在,它会按照一个标准MEM。 泄漏的定义。
也请记住,.NET有两种堆,一个是大型对象堆。 我相信,大约85K或更大的物体穿上这堆。 这堆具有比常规堆不同的生命周期的规则。
如果要创建大容量内存结构(字典的或名单的),它会谨慎地去查找什么确切的规则。
至于回收的进程终止内存,除非您运行在Win98或者当量,一切都放生就终止的操作系统。 唯一的例外是打开的跨进程的东西,另一个进程仍具有资源开放。
COM对象可以是棘手寿。 如果你总是使用IDispose
模式,你就安全了。 但我已经跨越实现了几个互操作程序集运行IDispose
。 这里的关键是调用Marshal.ReleaseCOMObject
,当你用它做。 COM对象仍然可以使用标准的COM引用计数。
我发现的.Net内存分析器有很好的帮助。NET中发现内存泄漏时。 这不是免费的,如微软CLR分析器,但速度更快,更在我看来一点。 一个
一个定义是: 无法释放不可访问内存,它可以不再分配过程的执行过程中被分配到新的进程。 它可以主要通过使用GC技术被治愈或通过自动工具检测到。
欲了解更多信息,请访问http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html 。