Ane*_*jee -1 c# garbage-collection memory-leaks
我正在修复大型项目中的内存泄漏,因此我将其缩小为一个Main()方法,其中Obj1
包含对另一个引用类型对象的引用的引用类型对象Obj2
.然后,我创建另一个类型的对象,Obj1
其中包含对同一Obj2
对象的引用.两个对象都使用块,如下所示:
using (dynamic obj1_a = new Obj1(args))
{
do some actions...
using (dynamic obj1_b = new Obj1(args))
{
do some more actions...
//Memory Snapshot 1 taken here
}
}
GC.Collect();
GC.WaitForPendingFinalizer();
GC.Collect();
//Memory Snapshot 2 taken here
Run Code Online (Sandbox Code Playgroud)
不知怎的,当我坐2个快照在上述评论的要点并加以比较,.NET内存探查表明,即使两个对象obj1_a
和obj1_b
已安置,他们没有被GC'ed.当我检查参考图时,我看到内存分析器说两个对象都是由我的Main()方法本身引用的.我已经完成了Main()方法的整个代码(它不是很复杂,只是创建,稍微修改然后测试垃圾收集),看看是否有一个变量引用仍然存在于这两个对象但是没有.我的Main()方法怎么可能将这些对象保存在内存中?重要的是他们收集垃圾(或者至少能够获得GC),因为它们包含对更多参考和值类型的引用,并且程序在没有它的情况下变得相当大.
即使已经处理了两个对象obj1_a和obj1_b,它们也没有被GC控制
您的陈述预先假定正在处理的对象与被垃圾收集器解除分配之间存在连接.确保您完全理解以下语句:处置对象对其是否有资格被收集没有任何影响.从GC的角度来看,Dispose
这只是一种方法.你不妨说"即使我打电话ToString
给一个物体,它仍然没有GC'".什么是ToString
具有与GC办?没有.什么是Dispose
具有与GC办?什么都没有.
现在,这略微夸大了案件.可终结的对象应该实现IDisposable,其Dispose应该调用SuppressFinalization.这对垃圾收集器有影响,因为终结对象总是至少存在一个比它们更长的集合,因为终结队列是根.但这里效果不是直接导致的Dispose
; 这只是处理者压制定型的惯例.抑制会对GC行为产生影响.
我的Main()方法怎么可能将这些对象保存在内存中?
当GC确定不存在包含对对象的直接或间接引用的活根时,GC将收集对象.
活动方法中的局部变量是活动根.
允许运行时完全由其自行决定并且出于任何原因,(1)确定本地永远不会再次读取并将其视为早期死亡,以及(2)即使控制已经过去,也要保持本地存活时间更长超出该变量的局部变量声明空间.
即使你obj1_a
和obj1_b
超出由GC运行时间范围,运行时完全允许假装他们是在顶部范围内声明的Main
,并允许让他们活着,直到Main
完成,这是以后的GC运行.
重要的是他们收集垃圾(或者至少能够获得GC),因为它们包含对更多参考和值类型的引用,并且程序在没有它的情况下变得相当大.
如果您需要对对象的生命周期进行细粒度控制,则具有自动内存释放的语言不符合您的要求.