我有一个物体,它永远存在。我正在删除我可以看到的所有引用,在使用它之后,但它仍然没有被收集。它的生命周期相当复杂,所以我不能确定所有的引用都被清除了。
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);我怎么才能找出它还有什么引用呢?为什么不收集呢?
发布于 2009-09-24 14:13:13
尝试使用内存分析器(例如ants),它会告诉你是什么让对象保持存活。尝试猜测这种类型的问题是非常困难的。
Red-gate有14天的试用期,应该有足够的时间来解决这个问题,并决定内存分析器是否能为您提供长期价值。
市场上有很多其他内存分析器(例如.NET Memory Profiler),它们中的大多数都有免费试用,但是我发现Red-Gate工具很容易使用,所以倾向于先尝试一下。
发布于 2009-09-24 14:15:28
你必须使用Windbg和Sosex扩展。
!DumpHeap和!GCRoot命令可以帮助您标识实例,以及使其保持活动状态的所有剩余引用。
发布于 2014-09-24 15:04:36
我用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:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll这将加载SOS.dll扩展。
然后,您可以使用GetAddress(x)获取对象的十六进制地址(例如8AB0CD40),然后使用:
!do 8AB0CD40
!GCRoot -all 8AB0CD40转储对象并查找对该对象的所有引用。
请记住,如果GC运行,它可能会更改对象的地址。
https://stackoverflow.com/questions/1471927
复制相似问题