如何使用SOS(或SOSEX)在WinDbg的某个字段中显示具有某些值的托管对象? [英] How to display managed objects with certain value in one of the fields in WinDbg using SOS (or SOSEX)?
问题描述
我的问题是这样的:
0:000> !DumpHeap-type Microsoft.Internal.ReadLock -stat
------------------------------
堆0
总共0个对象
------------------------------
堆1
总共0个对象
------------------------------
总共2
0个对象
------------------------------
堆3
总共0个对象
------------------------------
总共0个对象
统计:
MT计数TotalSize类名称
000007fef3d14088 74247 2375904 Microsoft.Internal.ReadLock
总共74247个对象
我读这个输出的方式是我的堆上有74,247 Microsoft.Internal.ReadLock
实例。但是,其中一些可能正在收集。
我只想显示那些未收到的收藏。
例如, 0000000080f88e90
是这些对象之一的地址,它是垃圾。我知道,因为:
0:000> !mroot 0000000080f88e90
找不到根路径。
0:000> !refs 0000000080f88e90 -target
引用0000000080f88e90的对象(Microsoft.Internal.ReadLock):
NONE
0:000> !do 0000000080f88e90
名称:Microsoft.Internal.ReadLock
MethodTable:000007fef3d14088
EEClass:000007fef3c63410
大小:32(0x20)个字节
文件:C:\Windows \Microsoft.Net\assembly\GAC_MSIL\System.ComponentModel.Composition\v4.0_4.0.0__b77a5c561934e089\System.ComponentModel.Composition.dll
字段:
MT字段偏移类型VT Attr值名称
000007fef3d13fb0 400001e 8 ... oft.Internal.Lock 0实例0000000080001010 _lock
000007fef0a8c7d8 400001f 10 System.Int32 1实例1 _isDisposed
可以看到, sosex.mroot
和 sosex.refs
表示没有人引用它,加上倾销它的字段显示它是通过
IDisposable
来处理的,所以对象是垃圾是有意义的(我知道是处置并不意味着物体是垃圾,但在这种情况下)。
现在我想显示所有不是垃圾的实例。我想我要使用 .foreach
命令。这样做:
.foreach(entry {!dumpheap-type Microsoft.Internal.ReadLock -short}){。if ???){.printf%p\\\
,entry}}
我的问题是我不知道进入 .if
条件。
我可以检查这个_isDisposed字段:
0:000> dd 0000000080f88e90 + 10 L1
00000000`80f88ea0 00000001
但。如果
期望一个表达式,并且我所有的都是一个命令输出。如果我知道如何从命令输出中提取信息并将其排列为表达式,那么我可以使用它作为 .if
条件并且很好。
所以,我的问题是 - 有没有办法把字段值作为适合 .if
的表达式?或者,是否可以以适合使用结果的方式解析命令输出作为 .if
条件?
我没有使用ReadLock对象的例子,但是我尝试使用Strings,这是我的结果:
.foreach(entry {!dumpheap -short-type Microsoft.Internal.ReadLock})
{
.if(poi($ {entry} +10)== 1)
{
.printf%p\\\
,$ {entry}
}
}
我正在使用poi()从地址获取指针大小数据。另请注意,我正在使用poi()和.printf中的 $ {entry} 不条目。您可能也希望在.if。$ / $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $
.foreach(entry {!dumpheap -short-type Microsoft.Internal.ReadLock}){.if(poi($ {entry} +10)== 1){.printf %p\\\
,$ {entry}}}
My problem is this:
0:000> !DumpHeap -type Microsoft.Internal.ReadLock -stat
------------------------------
Heap 0
total 0 objects
------------------------------
Heap 1
total 0 objects
------------------------------
Heap 2
total 0 objects
------------------------------
Heap 3
total 0 objects
------------------------------
total 0 objects
Statistics:
MT Count TotalSize Class Name
000007fef3d14088 74247 2375904 Microsoft.Internal.ReadLock
Total 74247 objects
The way I read this output is that I have 74,247 Microsoft.Internal.ReadLock
instances on my heap. However, some of them are probably pending collection.
I want to display only those which are not pending collection.
For example, 0000000080f88e90
is the address of one of these objects and it is garbage. I know it, because:
0:000> !mroot 0000000080f88e90
No root paths were found.
0:000> !refs 0000000080f88e90 -target
Objects referencing 0000000080f88e90 (Microsoft.Internal.ReadLock):
NONE
0:000> !do 0000000080f88e90
Name: Microsoft.Internal.ReadLock
MethodTable: 000007fef3d14088
EEClass: 000007fef3c63410
Size: 32(0x20) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.ComponentModel.Composition\v4.0_4.0.0.0__b77a5c561934e089\System.ComponentModel.Composition.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007fef3d13fb0 400001e 8 ...oft.Internal.Lock 0 instance 0000000080001010 _lock
000007fef0a8c7d8 400001f 10 System.Int32 1 instance 1 _isDisposed
As one can see, both sosex.mroot
and sosex.refs
indicate no one references it, plus dumping its fields reveals that it was disposed through IDisposable
, so it makes sense that the object is garbage (I know that being disposed does not imply the object is garbage, but it is in this case).
Now I want to display all those instances which are not garbage. I guess I am to use the .foreach
command. Something like this:
.foreach(entry {!dumpheap -type Microsoft.Internal.ReadLock -short}){.if (???) {.printf "%p\n", entry} }
My problem is that I have no idea what goes into the .if
condition.
I am able to inspect the _isDisposed field like this:
0:000> dd 0000000080f88e90+10 L1
00000000`80f88ea0 00000001
But .if
expects an expression and all I have is a command output. If I knew how to extract information from the command output and arrange it as an expression then I could use it as the .if
condition and be good.
So, my question is this - is there a way to get the field value as an expression suitable for .if
? Alternatively, is it possible to parse the command output in a way suitable for using the result as the .if
condition?
I didn't have an example which uses ReadLock objects, but I tried with Strings and this is my result:
.foreach (entry {!dumpheap -short -type Microsoft.Internal.ReadLock})
{
.if (poi(${entry}+10) == 1)
{
.printf "%p\n", ${entry}
}
}
I'm using poi() to get pointer size data from the address. Also note I'm using ${entry} not entry in both, poi() and .printf. You might also like !do ${entry} inside the .if.
In one line for copy/paste:
.foreach (entry {!dumpheap -short -type Microsoft.Internal.ReadLock}) {.if (poi(${entry}+10) == 1) {.printf "%p\n", ${entry}}}
这篇关于如何使用SOS(或SOSEX)在WinDbg的某个字段中显示具有某些值的托管对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!