C#GC没有收集没有根的对象
本文关键字:对象 C#GC | 更新日期: 2023-09-27 18:25:33
我从文件中读取一些数据(例如,1.00E+7个对象)到对象列表中。然后我将它们传递给另一个类,该类将对每个类进行转换,然后序列化到磁盘。在这个过程中,我有相当大的内存泄漏。
使用!dumpheap -stat
,我发现我的一些类占用了大量内存,例如:
MT count TotalSize ClassName
00185fd0 196180 7847200 Di3BMain.PeakDataClass
0070d25c 392429 9418296 System.Collections.Generic.List`1[[DI3.Lambda`2[[System.Int32, mscorlib],[Di3BMain.PeakDataClass, Di3Main]], Di3]]
00707038 392360 10986080 DI3.B`2[[System.Int32, mscorlib],[Di3BMain.PeakDataClass, Di3Main]]
00930a0c 15453 12821476 CSharpTest.Net.Collections.BPlusTree`2+Element[[System.Int32, mscorlib],[DI3.B`2[[System.Int32, mscorlib],[Di3BMain.PeakDataClass, Di3Main]], Di3]][]
7282fe8c 393241 13307220 System.Object[]
72843a70 250 641899364 System.Int32[]
考虑到数量和大小,很明显,正如我所期望的那样,创建了同一对象的许多实例(一个输出序列化对象对应一个输入对象)。但是,每个新对象都应该按照我从代码中期望的那样收集,代码的格式非常简化,如下所示:
serializer.Add(new ConvertedObject( ... ){ ... });
为了理解泄漏,我试图检查一些最大条目的根源;例如使用CCD_ 3的CCD_;但它给我的是Found 0 roots.
考虑到在所有这些统计数据之前,我使用以下代码强制GC
,我想知道为什么GC
没有收集任何没有根的大对象?!即使推了它!
GC.Collect();
GC.SuppressFinalize(this);
GC.WaitForPendingFinalizers();
!gcroot -all 00707038
值00707038
是方法表的地址。。要查找对象是否有根,您需要选择类的实例,即使用对象地址,而不是方法表地址。使用MT地址的dumpheap -mt
(无-stat
)将转储给定类的对象列表(在您的情况下,列表可能很长。因此,您可以想办法限制输出,或者在屏幕上转储了几个之后中断)
一旦有了对象地址,就在该地址上运行gcroot
。
- 另一方面,请注意,仅仅因为对象没有根,并不意味着GC没有收集它。根据对象所处的生成、GC上次运行给定生成的时间以及转储的时间,没有根的对象在转储中显示可能是正常的
GC可能不会收集每一代和每一个对象,除非它认为系统处于内存压力之下。