ClrMD是检查实时可执行文件或内存转储的好工具。要将所有托管堆对象转储为摘要,您可以使用
https://blogs.msdn.microsoft.com/dotnet/2013/05/01/net-crash-dump-and-live-process-inspection/
var stats = from o in heap.EnumerateObjects()
let t = heap.GetObjectType(o)
group o by t into g
let size = g.Sum(o => (uint)g.Key.GetSize(o))
orderby size
select new
{
Name = g.Key.Name,
Size = size,
Count = g.Count()
};
foreach (var item in stats)
Console.WriteLine("{0,12:n0} {1,12:n0} {2}", item.Size, item.Count, item.Name);
这很好用,相当于带有SOS扩展的Windbg中的!DumpHeap -stat 。对于回归测试,通常希望在测试后检查对象是否泄漏。这看起来非常适合上面的代码,但不幸的是它会产生误报,因为可能有些对象不再是 root,但它们仍会在摘要中报告。尽管没有泄漏,但这可能会导致报告的泄漏。
SOS已通过将-live 开关添加到!DumpHeap来缓解此问题。仅获取活动对象的等效ClrMD代码是什么,因此回归测试仅因真实原因而失败?
我想我需要使用ClrType.EnumerateRefsOfObjectCarefully递归地遍历堆栈,直到找到根对象(ClrHeap.EnumerateRoots),但这种方法需要许多临时哈希集来跟踪递归对象图。这是唯一的方法,还是在 MS 内部某个地方已经有一个正确且性能良好的示例可用(PerfView源?)。