【问题标题】:How to list all object in GC finalization list?如何列出 GC 终结列表中的所有对象?
【发布时间】:2015-05-20 10:28:31
【问题描述】:

我的程序崩溃了,它是VS的可视化工具,所以调试起来非常困难,我尝试制作dump并使用WinDbg研究它,但没有成功。

所以,现在我尝试以编程方式将我的手放在该列表上,但我不知道如何。谢谢。

【问题讨论】:

  • 哪个最终列表?当前活动的所有对象的列表(当 GC 观察到没有更多引用时)将被最终确定,或者所有对象的列表已经发生并且正在等待终结器线程访问它们?
  • 所以你想要 f-reachable 队列。
  • @Damien_The_Unbeliever: Re: “或者所有对象的列表已经发生了并且正在等待终结器线程访问它们” 这似乎没有据我了解.NET GC 是有道理的。对象的内存可能已经回收(垃圾收集),但对象可能还没有最终确定。但是似乎不可能一个对象已经完成但“终结器线程尚未访问它”。如果终结器线程尚未“访问”对象,则该对象未终结。
  • @stakx - 我的意思是“这已经发生在哪里”作为“当 GC 观察到没有更多引用时”
  • @Damien_The_Unbeliever:这清楚了,谢谢。

标签: c# garbage-collection finalization


【解决方案1】:

如果您想查看一个对象是否在终结队列或 f-reachable 队列中,当您启动 WinDBG 时,首先使用dumpheap -stat 或任何其他命令定位您的对象。找到对象地址后,您可以使用!FinalizeQueue,它会输出每一代有多少对象可终结,以及有多少对象准备终结。前者是finalization queue,后者是f-reachable queue。

例如:

0:003> !FinalizeQueue

要清理的同步块:0 个 MTA 接口 待发布:0 待发布的STA接口:0

第 0 代有 370 个可终结对象
(0000000000d29030->0000000000d29bc0)

第 1 代有 4 个可终结对象
(0000000000d29010->0000000000d29030)

第 2 代有 8 个可终结对象
(0000000000d28fd0->0000000000d29010)

准备完成 571 个对象
(0000000000d29bc0->0000000000d2ad98)

现在,您可以看到您的对象地址空间在哪里。

一个很棒的教程是available here

【讨论】:

  • 谢谢你,我知道了:)
  • @Yola 你知道这件事,但它没有帮助?
  • 是的,作为在 VS 中运行的线程,我可以转储所有 devenv 进程。而且我无法捕捉到转储的准确时刻。
  • @Yola 那我不知道你到底在问什么。
  • 是的,当然,我要求 f-reachable,因为我认为存在未正确释放本机资源的问题。
【解决方案2】:

我认为没有办法通过 .NET 的托管框架类库 (FCL) 进入最终队列。我怀疑如果您想以编程方式而不是debugging with WinDbg 执行此操作,您(就像 WinDbg 和类似工具一样)将需要为此使用 CLR 的非托管调试和分析 API。

看看ICORDebugGCReferenceEnum COM interface。您可以通过ICorDebugProcess5::EnumerateGCReferences 检索该类型的对象:

“为将被垃圾回收的对象提供枚举器。”

“集合中的COR_GC_REFERENCE对象由 [ICorDebugGCReferenceEnum::Next method] 代表三种对象:

  • 来自所有托管堆栈的对象。这包括托管代码中的实时引用以及公共语言运行时创建的对象。

  • 句柄表中的对象。这包括强引用(HNDTYPE_STRONGHNDTYPE_REFCOUNT)和模块中的静态变量。

  • 来自终结器队列的对象。终结器队列以对象为根,直到终结器运行为止。”

(我添加的超链接和重点。)

枚举器返回的每个对象都有一个字段type。您可能希望过滤该字段与值 CorGCReferenceType.CorReferenceFinalizer 匹配的对象。

【讨论】:

  • 感谢您的指导,我真的不知道如何使用我在 PC 上的 WDK 目录中找到的 cordebug.idl 和 cordebug.tlb 文件,也许您可​​以提供有关如何使用的任何链接这种物体?
  • @Yola:这是一个完全不同的问题,我相信以前有人问过。我建议您在 SO 或网络上进行一些搜索。无论如何,不​​确定 .NET 进程是否可以检查自己的运行时(我从来没有这样做过),但是如果您想使用 .NET 执行此操作,这里有一个提示:使用tlbimp 工具生成 .NET“主互操作程序集”,带有来自 .tlb 的 COM 互操作类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 2016-01-17
  • 2010-12-07
  • 2019-12-21
  • 1970-01-01
  • 2011-11-07
相关资源
最近更新 更多