在WinDbg中仅转储有根管理的对象和/或统计信息

时间:2013-12-24 20:43:04

标签: debugging windbg sos sosex

我的问题是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字符串提取到另一个文件,然后比较每个文件中的行数。当然有更好的方法: - (。

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

1 个答案:

答案 0 :(得分:4)

你对所有对象的循环已经很好了,只需要将!refs命令替换为只找到有根对象的其他东西。我的示例使用了Strings,因为我没有使用ReadLocks提供的应用程序。

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

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

垃圾对象如下所示:

Objects referencing 02703f30 (System.String):
NONE

如果第二行包含单词“follow”,您只对第一行的地址感兴趣。幸运的是,地址等于${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 接下来我们需要检查此标记是否等于跟随,这是由

完成的
.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。