在运行时查找对象的引用
我有一个永生的物体。 我删除了所有可以看到的引用,使用它之后,但仍然没有收集。 它的生命周期非常复杂,所以我不能确定所有引用都已被清除。
if ( container.Controls.Count > 0 ) { var controls = new Control[ container.Controls.Count ]; container.Controls.CopyTo( controls, 0 ); foreach ( var control in controls ) { container.Controls.Remove( control ); control.Dispose(); } controls = null; } GC.Collect(); GC.Collect(1); GC.Collect(2); GC.Collect(3);
我怎样才能找到它仍然有哪些参考? 为什么不收集?
尝试使用内存分析器 (例如ant )它会告诉你什么使对象保持活着。 试图第二次猜测这类问题非常困难。
Red-gate提供了14天的试用期,应该有足够的时间来解决这个问题,并决定内存分析器是否为您提供长期价值。
市场上有很多其他的内存分析器(例如.NET内存分析器 ),大多数都有免费试用,但是我发现Red-Gate工具很容易使用,所以最好先尝试一下。
你必须使用Windbg和Sosex扩展。
!DumpHeap
和!GCRoot
命令可以帮助您识别实例以及使其保持活动状态的所有剩余引用。
我一直在使用.NET Memory Profiler对我们的一个项目进行一些严肃的内存分析。 这是一个了解应用程序内存管理的好工具。 我没有得到这个信息的报酬:)但它只是帮了我很多。
我用SOS扩展解决了类似的问题(显然它不再适用于Visual Studio 2013,但适用于旧版本的Visual Studio)。
我使用下面的代码来获取我想跟踪引用的对象的地址:
public static string GetAddress(object o) { if (o == null) { return "00000000"; } else { unsafe { System.TypedReference tr = __makeref(o); System.IntPtr ptr = **(System.IntPtr**) (&tr); return ptr.ToString ("X"); } } }
然后,在Visual Studio 2012立即窗口中,在调试器中运行时,键入:
.load C:WindowsMicrosoft.NETFrameworkv4.0.30319sos.dll
这将加载SOS.dll
扩展名。
然后,您可以使用GetAddress(x)
来获取对象的hex地址(例如8AB0CD40
),然后使用:
!do 8AB0CD40 !GCRoot -all 8AB0CD40
转储对象并查找对象的所有引用。
请记住,如果GC运行,它可能会更改对象的地址。
.NET中的垃圾收集不是计数方案(例如COM),而是标记和扫描实现。 基本上,当GC感觉需要时,GC在“随机”时间运行,因此对象的收集不是确定性的。
但是,您可以手动触发集合(GC.Collect()),但可能必须等待终结器运行(GC.WaitForPendingFinalizers())。 但是,不鼓励在生产应用程序中执行此操作,因为它可能会影响内存管理的效率(GC运行过于频繁,或等待终结器运行)。 如果对象仍然存在,它实际上仍然在某处有一些实时引用。
它未被收集,因为您尚未删除对它的所有引用。 如果对象在应用程序中没有根,则GC将仅标记要收集的对象。
您使用什么方法检查GC以查看它是否收集了您的对象?
上述就是C#学习教程:在运行时查找对象的引用分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1019012.html