er-*_*r-v 21 .net c# garbage-collection
我有一个永生的物体.我删除了所有可以看到的引用,使用它之后,它仍然没有收集.它的生命周期非常复杂,所以我不能确定所有引用都已被清除.
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);
Run Code Online (Sandbox Code Playgroud)
我怎样才能找到它仍然有哪些参考?为什么不收集?
Ian*_*ose 15
尝试使用内存分析器(例如蚂蚁)它会告诉你什么使对象保持活着.试图第二次猜测这类问题非常困难.
Red-gate提供了14天的试用期,应该有足够的时间来解决这个问题,并决定内存分析器是否为您提供长期价值.
市场上有很多其他的内存分析器(例如.NET Memory Profiler),大多数都有免费试用版,但是我发现Red-Gate工具很容易使用,所以最好先尝试一下.
我解决了 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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在 Visual Studio 2012 立即窗口中,在调试器中运行时,键入:
.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll
Run Code Online (Sandbox Code Playgroud)
这将加载SOS.dll
扩展。
然后您可以使用GetAddress(x)
来获取对象的十六进制地址(例如8AB0CD40
),然后使用:
!do 8AB0CD40
!GCRoot -all 8AB0CD40
Run Code Online (Sandbox Code Playgroud)
转储对象并查找对该对象的所有引用。
请记住,如果 GC 运行,它可能会更改对象的地址。
归档时间: |
|
查看次数: |
17843 次 |
最近记录: |