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();

C#GC没有收集没有根的对象

  1. !gcroot -all 0070703800707038是方法表的地址。。要查找对象是否有根,您需要选择类的实例,即使用对象地址,而不是方法表地址。使用MT地址的dumpheap -mt(无-stat)将转储给定类的对象列表(在您的情况下,列表可能很长。因此,您可以想办法限制输出,或者在屏幕上转储了几个之后中断)

一旦有了对象地址,就在该地址上运行gcroot

  1. 另一方面,请注意,仅仅因为对象没有根,并不意味着GC没有收集它。根据对象所处的生成、GC上次运行给定生成的时间以及转储的时间,没有根的对象在转储中显示可能是正常的

GC可能不会收集每一代和每一个对象,除非它认为系统处于内存压力之下。