【问题标题】:Dumping only rooted managed objects and/or statistics on them inside WinDbg在 WinDbg 中仅转储有根的托管对象和/或关于它们的统计信息
【发布时间】:2013-12-28 06:13:31
【问题描述】:

我的问题是dumpheap -stat 返回了大量的对象,我不知道哪些是有根的,哪些不是。

好吧,如果我在单个地址上运行 !mroot!refs 命令,我可以,但这种方法不能很好地扩展到 dumpheap 报告的数千个对象。

例如,dumpheap -stat 包含以下行:

000007fef3d14088    74247      2375904 Microsoft.Internal.ReadLock

哇,74,247 个实例。但是,运行

.logopen c:\tmp\2\log.txt;.foreach (entry {!dumpheap -type Microsoft.Internal.ReadLock -short}){!refs ${entry} -target};.logclose

表明DumpHeap 报告的每个实例实际上都是未回收的垃圾!

我如何发现每个实例都是垃圾是另一个问题。我必须将所有NONE 字符串提取到一个文件中,并将所有Objects referencing 字符串提取到另一个文件中,然后比较每个文件中的行数。当然有更好的方法:-(。

无论如何,我想知道如何只关注根对象。理想情况下,我希望获得此类对象的统计信息和详细信息。

【问题讨论】:

  • 我的建议是给 Steve Johnson(SOSEX 的作者)写一封电子邮件,询问 !refs 和 !mroot 上的 -short 选项,类似于 !dumpheap -short,以便可以在进一步处理中使用它。

标签: debugging windbg sos sosex


【解决方案1】:

您对所有对象的循环已经很棒了,只是需要将 !refs 命令替换为仅找到根对象的其他命令。我的示例使用字符串,因为我没有使用 ReadLocks 的应用程序。

!refs 命令有两种可能的输出。引用的对象输出例如

Objects referencing 02703f18 (System.String):
follow 02703a88       128   System.Globalization.NumberFormatInfo

垃圾对象如下所示:

Objects referencing 02703f30 (System.String):
NONE

您只对第一行的地址感兴趣,以防第二行包含单词“follows”。幸运的是,地址等于${entry},所以我们实际上不需要它。否则你会在same trouble like I am

这会将我带到this question about .if

您可以在 !refs 的输出上再次使用 .foreach。让我们先在单个对象上看一下:

.foreach (reftoken {!refs 027045cc -target}) { .printf "${reftoken}\n" }

每行打印一个单词,我们只对第五个单词感兴趣,这意味着我们最初可以跳过 4 个项目,然后跳过其余的,这给了我们

.foreach /pS 4 /ps 3 (reftoken {!refs 027045cc -target}) { .printf "${reftoken}\n" }

出于稳健性目的,我们使用/ps 99
接下来我们需要检查这个token是否等于follow,这是由

完成的
.if ($sicmp("${reftoken}","follow") == 0) { .echo found follow }

然后将它们组合在一起:

.foreach (entry {!dumpheap -type System.String -short})
{
   .foreach /pS 4 /ps 99 (reftoken {!refs ${entry} -target}) 
   { 
      .if ($sicmp("${reftoken}","follow") == 0) 
      { 
            .printf "${entry}\n"
      } 
   }
}

一行:

 .foreach (entry {!dumpheap -type System.String -short}){.foreach /pS 4 /ps 99 (reftoken {!refs ${entry} -target}) {.if ($sicmp("${reftoken}","follow") == 0) {.printf "${entry}\n"}}}

当然,您可以将 .print 替换为对您的情况有帮助的任何其他命令。

我希望您可以修改此示例以使用 ReadLock。

【讨论】:

  • 这是一个很好的答案。但我需要澄清一下。 $sicmp 是什么?它是指向 CRT 中的字符串比较函数的指针吗?您能说明如何设置它的值吗?
  • $iscmp() 是一个 MASM 运算符(函数),其行为类似于 Win32 stricmp()。其他功能见.hh MASM。第一个参数"${reftoken}".foreach命令创建。
猜你喜欢
  • 2020-08-12
  • 1970-01-01
  • 2011-10-23
  • 2020-11-28
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多