Csharp/C#教程:在运行时查找对象的引用分享


在运行时查找对象的引用

我有一个永生的物体。 我删除了所有可以看到的引用,使用它之后,但仍然没有收集。 它的生命周期非常复杂,所以我不能确定所有引用都已被清除。

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

(0)
上一篇 2022年1月4日
下一篇 2022年1月4日

精彩推荐