Debugging 在WinDbg中仅转储根托管对象和/或其统计信息

Debugging 在WinDbg中仅转储根托管对象和/或其统计信息,debugging,windbg,sos,sosex,Debugging,Windbg,Sos,Sosex,我的问题是dumpheap-stat返回了大量的对象,我不知道哪些是根对象,哪些不是根对象 嗯,如果我运行,我可以!mroot或!在单个地址上引用命令,但这种方法不能很好地扩展到dumpheap报告的数千个对象 例如,dumpheap-stat包含以下行: 000007fef3d14088 74247 2375904 Microsoft.Internal.ReadLock 哇,74247个实例。然而,运行 .logopen c:\tmp\2\log.txt;.foreach (

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

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

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

000007fef3d14088    74247      2375904 Microsoft.Internal.ReadLock
哇,74247个实例。然而,运行

.logopen c:\tmp\2\log.txt;.foreach (entry {!dumpheap -type Microsoft.Internal.ReadLock -short}){!refs ${entry} -target};.logclose
显示
DumpHeap
报告的每个实例实际上都是未回收的垃圾

我如何发现每个实例都是垃圾是另一个问题。我必须将所有
NONE
字符串提取到一个文件中,将引用
字符串的所有
对象提取到另一个文件中,然后比较每个文件中的行数。当然还有更好的办法:——(


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

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

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

Objects referencing 02703f18 (System.String):
follow 02703a88       128   System.Globalization.NumberFormatInfo
垃圾对象的外观如下所示:

Objects referencing 02703f30 (System.String):
NONE
如果第二行包含单词“follows”,则您只对第一行的地址感兴趣。幸运的是,该地址等于
${entry}
,因此我们实际上不需要它。否则,您将处于

这让我想到了

您可以在!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

接下来我们需要检查这个令牌是否等于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。

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

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

Objects referencing 02703f18 (System.String):
follow 02703a88       128   System.Globalization.NumberFormatInfo
垃圾对象的外观如下所示:

Objects referencing 02703f30 (System.String):
NONE
如果第二行包含单词“follows”,则您只对第一行的地址感兴趣。幸运的是,该地址等于
${entry}
,因此我们实际上不需要它。否则,您将处于

这让我想到了

您可以在!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

接下来我们需要检查这个令牌是否等于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。

我的建议是给Steve Johnson(SOSEX的作者)写一封电子邮件,要求在!refs和!mroot上提供类似于!dumpheap的-short选项,以便在进一步处理中使用。我的建议是给Steve Johnson(SOSEX的作者)写一封电子邮件一封要求在!refs和!mroot上提供-short选项的电子邮件类似于!dumpheap-short,以便在进一步处理中使用。这是一个很好的答案。但我需要澄清一下。什么是
$sicmp
?它是指向CRT中字符串比较函数的指针吗?您能说明如何设置它的值吗?
$iscmp()
是一个MASM运算符(函数),其行为类似于Win32 stricmp()。有关其他函数,请参见
.hh MASM
。第一个参数
“${reftoken}”
是由
.foreach
命令创建的。这是一个很好的答案。但我需要澄清一下。什么是
$sicmp
?它是指向CRT中字符串比较函数的指针吗?您能说明如何设置它的值吗?
$iscmp()
是一个MASM运算符(函数),其行为类似于Win32 stricmp()。有关其他函数,请参见
.hh MASM
。第一个参数
“${reftoken}”
.foreach
命令创建。