2025年2月24日 星期一 甲辰(龙)年 腊月廿四 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 软件应用 > 反汇编工具

WinDbg常用命令

时间:11-10来源:作者:点击数:29
CDSY,CDSY.XYZ

前一篇文章介绍了WinDbg入门,本篇主要介绍WinDbg常用命令和用法。 调试程序的CPU满载问题,关键是要知道程序当前正在进行什么操作。假如我们在cpu满载时创建了一个dump文件,使用下面几个命令可以查看当前程序正在进行什么处理:

.time

运行.time命令会显示时间相关的信息,如系统运行时间,进程运行时间和CPU花费在内核态和用户态的时间。

  • 0:000> .time
  • Debug session time: Tue Oct 23 08:38:35.000 2007 (GMT+1)
  • System Uptime: 4 days 17:48:01.906
  • Process Uptime: 0 days 0:24:37.000
  • Kernel time: 0 days 0:04:23.000
  • User time: 0 days 0:03:28.000

你可以看到系统已正常运行超过4天,进程运行了24分钟,CPU在内核态和用户态累积使用了8分钟。根据进程时间和CPU时间能大概估算出CPU使用率平均值是32.5%。

!threadpool

通过!threadpool命令我们能准确知道创建dump时cpu的使用率。也能知道在队列中的待处理请求数,Completion Port(IOCP)线程数和定时器time数。

  • 0:000> !threadpool
  • CPU utilization 100%
  • Worker Thread: Total: 5 Running: 4 Idle: 1 MaxLimit: 200 MinLimit: 2
  • Work Request in Queue: 16
  • Unknown Function: 6a2d945d Context: 023ede30
  • Unknown Function: 6a2d945d Context: 023ee1e8
  • AsyncTimerCallbackCompletion TimerInfo@11b53760
  • Unknown Function: 6a2d945d Context: 023ee3a8
  • Unknown Function: 6a2d945d Context: 023e3040
  • Unknown Function: 6a2d945d Context: 023ee178
  • Unknown Function: 6a2d945d Context: 023edfb0
  • AsyncTimerCallbackCompletion TimerInfo@11b36428
  • AsyncTimerCallbackCompletion TimerInfo@11b53868
  • Unknown Function: 6a2d945d Context: 023ee060
  • Unknown Function: 6a2d945d Context: 023ee290
  • Unknown Function: 6a2d945d Context: 023eded0
  • Unknown Function: 6a2d945d Context: 023edd88
  • Unknown Function: 6a2d945d Context: 023ede98
  • Unknown Function: 6a2d945d Context: 023ee258
  • Unknown Function: 6a2d945d Context: 023edfe8
  • --------------------------------------
  • Number of Timers: 9
  • --------------------------------------
  • Completion Port Thread:Total: 3 Free: 3 MaxFree: 4 CurrentLimit: 2 MaxLimit: 200 MinLimit: 2

我们可以看到当前CPU已100%使用率,我们进入下一命令。

!runaway

这个命令用于显示所有正在运行的线程和它们的CPU使用率。这个命令对于查找高CPU使用率问题很有帮助!

  • 0:000> !runaway
  • User Mode Time
  • Thread Time
  • 25:1a94 0 days 0:00:39.937
  • 16:1bc0 0 days 0:00:38.390
  • 50:1e8c 0 days 0:00:08.859
  • 52:1e40 0 days 0:00:08.687
  • 20:1c2c 0 days 0:00:08.234
  • 51:1340 0 days 0:00:08.171
  • 21:1bcc 0 days 0:00:06.953
  • 26:13ec 0 days 0:00:06.671
  • 44:131c 0 days 0:00:03.906
  • 22:d8c 0 days 0:00:03.375
  • 33:78c 0 days 0:00:02.656
  • 34:1a8c 0 days 0:00:00.906
  • 29:1f5c 0 days 0:00:00.828
  • 6:e28 0 days 0:00:00.625
  • 5:1c78 0 days 0:00:00.546
  • 23:14a4 0 days 0:00:00.484
  • 4:5ac 0 days 0:00:00.437
  • 45:5dc 0 days 0:00:00.421
  • 3:13b4 0 days 0:00:00.421
  • 47:19c8 0 days 0:00:00.375
  • 28:1b6c 0 days 0:00:00.250
  • 46:1dac 0 days 0:00:00.156
  • 7:1dd8 0 days 0:00:00.109
  • 48:cdc 0 days 0:00:00.093
  • 49:1eac 0 days 0:00:00.062
  • 15:1a64 0 days 0:00:00.062
  • 0:1804 0 days 0:00:00.046
  • 36:4a4 0 days 0:00:00.031
  • 11:1eb4 0 days 0:00:00.031
  • 1:10b4 0 days 0:00:00.031
  • 31:16ac 0 days 0:00:00.015
  • 14:4ac 0 days 0:00:00.015
  • 2:186c 0 days 0:00:00.015
  • 59:590 0 days 0:00:00.000
  • 58:294 0 days 0:00:00.000
  • 57:16d0 0 days 0:00:00.000
  • 56:1578 0 days 0:00:00.000
  • 55:1428 0 days 0:00:00.000
  • 54:16d8 0 days 0:00:00.000
  • 53:fd8 0 days 0:00:00.000
  • 43:1b8c 0 days 0:00:00.000
  • 42:1c24 0 days 0:00:00.000
  • 41:1e2c 0 days 0:00:00.000
  • 40:11b0 0 days 0:00:00.000
  • 39:edc 0 days 0:00:00.000
  • 38:1a08 0 days 0:00:00.000
  • 37:171c 0 days 0:00:00.000
  • 35:1254 0 days 0:00:00.000
  • 32:1f9c 0 days 0:00:00.000
  • 30:1ae8 0 days 0:00:00.000
  • 27:190c 0 days 0:00:00.000
  • 24:1d2c 0 days 0:00:00.000
  • 19:1e38 0 days 0:00:00.000
  • 18:ee4 0 days 0:00:00.000
  • 17:fb8 0 days 0:00:00.000
  • 13:1b54 0 days 0:00:00.000
  • 12:1a48 0 days 0:00:00.000
  • 10:f64 0 days 0:00:00.000
  • 9:1024 0 days 0:00:00.000
  • 8:1b78 0 days 0:00:00.000

你可以看到运行线程的总时间和使用.time命令看到的总cpu使用时间并不相等。原因很简单,因为线程被重复使用或回收了。这也意味着一个线程的CPU使用时间可能是处理多个请求的结果。

!threads

!threads显示当前所有的托管线程信息。输出如下:

  • 0:000> !threads
  • ThreadCount: 48
  • UnstartedThread: 0
  • BackgroundThread: 29
  • PendingThread: 0
  • DeadThread: 19
  • Hosted Runtime: no
  • PreEmptive GC Alloc Lock
  • ID OSID ThreadOBJ State GC Context Domain Count APT Exception
  • 16 1 1bc0 001fccd0 1808220 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • 22 2 d8c 002016f0 b220 Enabled 00000000:00000000 0019daf0 0 MTA (Finalizer)
  • 14 4 4ac 00242e58 880a220 Enabled 00000000:00000000 0019daf0 0 MTA (Threadpool Completion Port)
  • 23 5 14a4 11b39f18 80a220 Enabled 00000000:00000000 0019daf0 0 MTA (Threadpool Completion Port)
  • 24 6 1d2c 11b41ad8 1220 Enabled 00000000:00000000 0019daf0 0 Ukn
  • 25 7 1a94 11b46c70 180b220 Enabled 27240c98:27241fd8 11b42540 1 MTA (Threadpool Worker)
  • 26 9 13ec 12ce2888 200b220 Enabled 2a9f1434:2a9f33c0 11b42540 0 MTA
  • 27 a 190c 12d85eb8 200b220 Enabled 00000000:00000000 11b42540 0 MTA
  • 29 b 1f5c 13df6a50 200b220 Enabled 2ab1da6c:2ab1f1c0 11b42540 0 MTA
  • 30 c 1ae8 12d44a58 b220 Enabled 00000000:00000000 11b42540 0 MTA
  • 31 d 16ac 12e2e008 200b220 Enabled 2a81348c:2a8153c0 11b42540 1 MTA
  • 5 e 1c78 12da2160 220 Enabled 00000000:00000000 0019daf0 0 Ukn
  • 33 8 78c 11b674c8 200b220 Enabled 2707b818:2707c1d8 11b42540 0 MTA
  • 34 12 1a8c 13f163c8 220 Enabled 00000000:00000000 0019daf0 0 Ukn
  • 36 13 4a4 13eef718 200b220 Enabled 2a7db4a4:2a7dd3c0 11b42540 0 MTA
  • 4 14 5ac 13ef2008 220 Enabled 00000000:00000000 0019daf0 0 Ukn
  • 42 10 1c24 13f0e950 880b220 Enabled 00000000:00000000 0019daf0 0 MTA (Threadpool Completion Port)
  • 6 11 e28 13f16008 220 Enabled 00000000:00000000 0019daf0 0 Ukn
  • 3 f 13b4 13eba008 220 Enabled 00000000:00000000 0019daf0 0 Ukn
  • 43 15 1b8c 140db008 880b220 Enabled 00000000:00000000 0019daf0 0 MTA (Threadpool Completion Port)
  • 44 17 131c 140ceb28 200b220 Enabled 272288c8:27229fd8 11b42540 0 MTA
  • 45 1d 5dc 140cd0a0 220 Enabled 00000000:00000000 0019daf0 0 Ukn
  • 47 20 19c8 1651a008 220 Enabled 00000000:00000000 0019daf0 0 Ukn
  • XXXX 24 0 16468880 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • 46 1f 1dac 1650ab48 220 Enabled 00000000:00000000 0019daf0 0 Ukn
  • XXXX 1a 0 140d5008 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 16 0 140c5008 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • 50 3 1e8c 14064420 180b220 Enabled 27246f54:27247fd8 11b42540 1 MTA (Threadpool Worker)
  • XXXX 35 0 1406e800 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • 51 36 1340 140df008 180b220 Enabled 2adec9cc:2aded1c0 11b42540 1 MTA (Threadpool Worker)
  • XXXX 37 0 16566868 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • 48 38 cdc 16578840 220 Enabled 00000000:00000000 0019daf0 0 Ukn
  • XXXX 39 0 16566c28 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 3b 0 1646b8b0 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 3c 0 16674008 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 3d 0 16676418 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 3e 0 16676fb8 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 3f 0 16674d48 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 40 0 1667de10 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 41 0 16680050 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 42 0 166812e8 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 43 0 16683e60 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • 52 44 1e40 165259e8 180b220 Enabled 2adf126c:2adf31c0 11b42540 1 MTA (Threadpool Worker)
  • XXXX 45 0 165b7c08 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 46 0 165aa3d8 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 47 0 165242c8 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • XXXX 48 0 165e9500 1801820 Enabled 00000000:00000000 0019daf0 0 Ukn (Threadpool Worker)
  • 49 3a 1eac 165676f0 220 Enabled 00000000:00000000 0019daf0 0 Ukn

线程ID为XXXX表示该线程已结束,并在等待回收。我们也能看到线程ID为22的线程正在终结(finalizer)。假如我们使用!runaway命令时看到22线程有大量的cpu活动,可能我们的程序有终结(finalizer)问题。

切换到指定线程

要切换到指定的线程,可以使用下面的格式命令:~[thread id]s,假如我们要切换到50线程,命令如下:

  • 0:000> ~50s

现在我们已切换到线程50,可以使用很多其他有用的命令。

!clrstack

!clrstack显示当前线程的堆栈信息,通过指定“-p”参数,还能看到方法调用的参数和局部变量信息。 下面是线程50的堆栈信息:

  • 0:050> !clrstack
  • OS Thread Id: 0x1e8c (50)
  • ESP EIP
  • 17a9e750 7d61c828 [NDirectMethodFrameSlim: 17a9e750] System.DirectoryServices.Protocols.Wldap32.ldap_bind_s(IntPtr, System.String, System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX, System.DirectoryServices.Protocols.BindMethod)
  • 17a9e768 14df70f9 System.DirectoryServices.Protocols.LdapConnection.BindHelper(System.Net.NetworkCredential, Boolean)
  • 17a9e794 14df6de0 System.DirectoryServices.Protocols.LdapConnection.Bind()
  • 17a9e79c 14df59e9 System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(System.DirectoryServices.Protocols.DirectoryRequest, Int32 ByRef)
  • 17a9e8b8 14df56e8 System.DirectoryServices.Protocols.LdapConnection.SendRequest(System.DirectoryServices.Protocols.DirectoryRequest, System.TimeSpan)
  • 17a9e8bc 14df5657 [InlinedCallFrame: 17a9e8bc]

从下向上看,我们能知道LdapConnection调用了SendRequest方法,而SendRequest又调用了SendRequestHelper方法等等。 如果我们执行“!clrstack -p”命令,我们得到信息:

  • 0:050> !clrstack -p
  • OS Thread Id: 0x1e8c (50)
  • ESP EIP
  • 17a9e750 7d61c828 [NDirectMethodFrameSlim: 17a9e750] System.DirectoryServices.Protocols.Wldap32.ldap_bind_s(IntPtr, System.String, System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX, System.DirectoryServices.Protocols.BindMethod)
  • 17a9e768 14df70f9 System.DirectoryServices.Protocols.LdapConnection.BindHelper(System.Net.NetworkCredential, Boolean)
  • PARAMETERS:
  • this = 0x271fdfe0
  • newCredential =
  • needSetCredential =
  • 17a9e794 14df6de0 System.DirectoryServices.Protocols.LdapConnection.Bind()
  • PARAMETERS:
  • this =
  • 17a9e79c 14df59e9 System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(System.DirectoryServices.Protocols.DirectoryRequest, Int32 ByRef)
  • PARAMETERS:
  • this = 0x271fdfe0
  • request = 0x27246e38
  • messageID = 0x17a9e8ec
  • 17a9e8b8 14df56e8 System.DirectoryServices.Protocols.LdapConnection.SendRequest(System.DirectoryServices.Protocols.DirectoryRequest, System.TimeSpan)
  • PARAMETERS:
  • this = 0x271fdfe0
  • request = 0x27246e38
  • requestTimeout =
  • 17a9e8bc 14df5657 [InlinedCallFrame: 17a9e8bc]

我们可以看到DirectoryRequest参数传递给了SendRequest和SendRequestHelper,要查看DirectoryRequest的相关信息,我们只需复制它的地址(0x27246e38),并在下个命令中使用。

!dumpobject (!do)

这是另外一个重要的命令。Dumpobject会打印出指定地址的对象的相关信息。我们使用刚才的地址试下:

  • 0:050> !do 0x27246e38
  • Name: System.DirectoryServices.Protocols.SearchRequest
  • MethodTable: 14b394c4
  • EEClass: 14d97ce0
  • Size: 52(0x34) bytes
  • GC Generation: 0
  • (C:\WINDOWS\assembly\GAC_MSIL\System.DirectoryServices.Protocols\2.0.0.0__b03f5f7f11d50a3a\System.DirectoryServices.Protocols.dll)
  • Fields:
  • MT Field Offset Type VT Attr Value Name
  • 02c39310 4000102 4 System.String 0 instance 00000000 directoryRequestID
  • 14b398bc 4000103 8 ...ControlCollection 0 instance 27246e90 directoryControlCollection
  • 02c39310 4000111 c System.String 0 instance 27246d00 dn
  • 12579f5c 4000112 10 ....StringCollection 0 instance 27246eb4 directoryAttributes
  • 02c36ca0 4000113 14 System.Object 0 instance 27246ddc directoryFilter
  • 14b39344 4000114 18 System.Int32 1 instance 1 directoryScope
  • 14b393fc 4000115 1c System.Int32 1 instance 0 directoryRefAlias
  • 0fd3da00 4000116 20 System.Int32 1 instance 0 directorySizeLimit
  • 1202af88 4000117 28 System.TimeSpan 1 instance 27246e60 directoryTimeLimit
  • 120261c8 4000118 24 System.Boolean 1 instance 0 directoryTypesOnly

通过打印的信息,可以知道它是System.DirectoryServices.Protocols.SearchRequest的一个对象,而显示的都是 System.DirectoryServices.Protocols.SearchRequest的属性值。要知道SearchRequest类的相关属性信息,可以查看MSDN。当前我们已有RequestId, Scope和DistinguishedName等等。 所以,假如我们想知道SearchRequest对象的DistinguishedName属性值,即是上面列表中的dn,我们只需再复制它的地址(27246d00),并再次使用!dumpobject命令。因为DistinguishedName是System.String类型,所以输出结果很明显:

  • 0:050> !do 27246d00
  • Name: System.String
  • MethodTable: 02c39310
  • EEClass: 0fb610ac
  • Size: 112(0x70) bytes
  • GC Generation: 0
  • (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
  • String: CN=Dummy,CN=Accounts,CN=useradm,DC=dummy,DC=net
  • Fields:
  • MT Field Offset Type VT Attr Value Name
  • 0fd3da00 4000096 4 System.Int32 1 instance 48 m_arrayLength
  • 0fd3da00 4000097 8 System.Int32 1 instance 47 m_stringLength
  • 0fb80010 4000098 c System.Char 1 instance 43 m_firstChar
  • 02c39310 4000099 10 System.String 0 shared static Empty
  • >> Domain:Value 0019daf0:03380310 11b42540:03380310 << 0fb86d44 400009a 14 System.Char[] 0 shared static WhitespaceChars >> Domain:Value 0019daf0:03380324 11b42540:033855bc <<

通过输出的信息我们很容易知道DistinguishedName属性的值是“CN=Dummy,CN=Accounts,CN=useradm,DC=dummy,DC=net”。如果我们想查看更多内容,只需继续使用!dumpobject命令即可。

!dumpstackobjects (!dso)

使用该命令我们可以查看到当前线程的堆栈引用的所有托管对象。打印信息如下:

  • 0:050> !dso
  • OS Thread Id: 0x1e8c (50)
  • ESP/REG Object Name
  • 17a9e534 0741f860 System.RuntimeType
  • 17a9e6b8 271fdfe0 System.DirectoryServices.Protocols.LdapConnection
  • 17a9e6bc 27246f20 System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX
  • 17a9e740 271fdfe0 System.DirectoryServices.Protocols.LdapConnection
  • 17a9e744 27246f20 System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX
  • 17a9e764 27246f20 System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX
  • 17a9e768 271fdfe0 System.DirectoryServices.Protocols.LdapConnection
  • 17a9e780 271fdfe0 System.DirectoryServices.Protocols.LdapConnection
  • 17a9e784 27246e38 System.DirectoryServices.Protocols.SearchRequest
  • 17a9e794 271fdf14 System.DirectoryServices.Protocols.LdapDirectoryIdentifier
  • 17a9e7a8 27246ef8 System.Collections.ArrayList
  • 17a9e7bc 27246ef8 System.Collections.ArrayList
  • 17a9e7c8 271fdfe0 System.DirectoryServices.Protocols.LdapConnection
  • 17a9e8a4 27246e38 System.DirectoryServices.Protocols.SearchRequest
  • 17a9e8d0 27246ed8 System.Object[] (System.Object[])
  • 17a9e8e0 073ff6b8 System.String cn
  • 17a9e8e4 271fdfe0 System.DirectoryServices.Protocols.LdapConnection
  • 17a9e8f4 27246d00 System.String CN=Dummy,CN=Accounts,CN=useradm,DC=Dummy,DC=net
  • 17a9e8f8 271fdfe0 System.DirectoryServices.Protocols.LdapConnection
  • 17a9e8fc 27246e38 System.DirectoryServices.Protocols.SearchRequest
  • 17a9e910 03380310 System.String
  • 17a9e914 27246e24 System.Object[] (System.String[])
  • 17a9e918 272399a8 System.String CN=OID-Dummy-ABC123,CN=Dummy,CN=Accounts,CN=useradm,DC=Dummy,DC=net
  • 17a9e91c 27246ddc System.String (CN=OID-Dummy-ABC123)
  • ...etc...

这个命令对于查找当前线程引用了那些对象很有用。假如你想查看某一对象,只需复制[Object]字段的地址,并使用 !dumpobject命令:

  • 0:050> !do 271fdfe0
  • Name: System.DirectoryServices.Protocols.LdapConnection
  • MethodTable: 14a2040c
  • EEClass: 149daf08
  • Size: 56(0x38) bytes
  • (C:\WINDOWS\assembly\GAC_MSIL\System.DirectoryServices.Protocols\2.0.0.0__b03f5f7f11d50a3a\System.DirectoryServices.Protocols.dll)
  • Fields:
  • MT Field Offset Type VT Attr Value Name
  • 14a2078c 40000c3 4 ...NetworkCredential 0 instance 00000000 directoryCredential
  • 14a2144c 40000c4 8 ...ificateCollection 0 instance 271fe018 certificatesCollection
  • 1202af88 40000c5 10 System.TimeSpan 1 instance 271fdff0 connectionTimeOut
  • 1466fe50 40000c6 c ...rectoryIdentifier 0 instance 271fdf14 directoryIdentifier
  • 14a2034c 4000236 24 System.Int32 0 instance 2 connectionAuthType
  • 14a223a4 4000237 18 ...dapSessionOptions 0 instance 271fe2d8 options
  • 0fb896d8 4000238 28 System.IntPtr 0 instance 564180944 ldapHandle
  • 120261c8 4000239 2c System.Boolean 0 instance 0 disposed
  • 120261c8 400023a 2d System.Boolean 0 instance 0 bounded
  • 120261c8 400023b 2e System.Boolean 0 instance 0 needRebind
  • 14a22084 400023e 1c ...pResponseCallback 0 instance 271fe03c fd
  • 120261c8 4000243 2f System.Boolean 0 instance 0 setFQDNDone
  • 120261c8 4000244 30 System.Boolean 0 instance 1 automaticBind
  • 120261c8 4000245 31 System.Boolean 0 instance 1 needDispose
  • 120261c8 4000246 32 System.Boolean 0 instance 1 connected
  • 14a2267c 4000247 20 ...s.QUERYCLIENTCERT 0 instance 271fe394 clientCertificateRoutine
  • 0fd314bc 400023c 20 ...ections.Hashtable 0 shared static handleTable
  • >> Domain:Value 0019daf0:NotInit 11b42540:073fe504 < <
  • 02c36ca0 400023d 24 System.Object 0 shared static objectLock
  • >> Domain:Value 0019daf0:NotInit 11b42540:073fe53c < <
  • 0fd314bc 400023f 28 ...ections.Hashtable 0 shared static asyncResultTable
  • >> Domain:Value 0019daf0:NotInit 11b42540:073fe610 < <
  • 14a21864 4000240 2c ...lResultsProcessor 0 shared static partialResultsProcessor
  • >> Domain:Value 0019daf0:NotInit 11b42540:073fe678 < <
  • 12305e94 4000241 30 ....ManualResetEvent 0 shared static waitHandle
  • >> Domain:Value 0019daf0:NotInit 11b42540:073fe64c < <
  • 14a21954 4000242 34 ...lResultsRetriever 0 shared static retriever
  • >> Domain:Value 0019daf0:NotInit 11b42540:073fe6a8 < <

!dumparray (!da)

你可能已经注意到有很多对象数组在堆栈中,在上面的列表中查找System.Object[]类型就能找到。如果你对对象数组使用 !dumpobject命令,你只能看到数组信息,而不能看到数组的内容信息,要看到数组内容信息,就需要使用!dumparray命令,或简称!da:

  • 0:050> !do 27239b98
  • Name: System.Object[]
  • MethodTable: 02c3896c
  • EEClass: 02c388ec
  • Size: 24(0x18) bytes
  • Array: Rank 1, Number of elements 2, Type CLASS
  • Element Type: System.String
  • Fields:
  • None
  • 0:050> !da 27239b98
  • Name: System.String[]
  • MethodTable: 02c3896c
  • EEClass: 02c388ec
  • Size: 24(0x18) bytes
  • Array: Rank 1, Number of elements 2, Type CLASS
  • Element Methodtable: 02c39310
  • [0] 272399a8
  • [1] 27239a44

通过!dumparray命令我们能知道该数组对象是字符串数组,并给出了数组项的地址。再使用!dumpobject命令我们就能看到数组项的具体内容。 !objsize 如果你查看上面打印的信息,可以看到对象的大小是24字节。从某方面来说,这是对的,24字节是System.Object[]数组对象本身大小,但并不包括数组内容的大小!要获得整个对象的大小,就要使用到 !objsize命令:

  • 0:050> !objsize 27239b98
  • sizeof(27239b98) =          348 (       0x15c) bytes (System.Object[])

!objsize会遍历对象引用的所有子对象,并计算出总的大小。如上面数组对象和它的内容的总大小是348字节。 如果对象有引用很多子对象,那么!objsize会花费较多的时间计算出总大小。

!dumpheap

这是另一个较频繁使用的命令。!dumpheap会打印出所有在托管堆中的对象信息。直接执行该命令会打印出大量的信息,所以一般使用时都至少带上一个参数。加上-stat参数后会输出总结后的信息,如下面是截取的是!dumpheap -stat命令输出的一部分:

  • 0:050> !dumpheap -stat
  • ------------------------------
  • Heap 0
  • total 2754508 objects
  • ------------------------------
  • Heap 1
  • total 2761329 objects
  • ------------------------------
  • total 5515837 objects
  • Statistics:
  •       MT    Count    TotalSize Class Name
  • 16e0a6d8        1           12 System.Collections.Generic.ObjectEqualityComparer`1[[System.Data.ProviderBase.DbConnectionInternal, System.Data]]
  • 16d9cd9c        1           12 System.Xml.Serialization.Configuration.DateTimeSerializationSection+DateTimeSerializationMode
  • 16d9bf30        1           12 System.Diagnostics.OrdinalCaseInsensitiveComparer
  • 16d9112c        1           12 System.Xml.Serialization.NameTable
  • 16d7f664        1           12 System.Xml.Serialization.TempAssemblyCache
  • 163ea85c        1           12 System.Data.Res
  • 1501e4c4        1           12 System.Collections.Generic.ObjectEqualityComparer`1[[System.Web.UI.Control, System.Web]]
  • 14efb138        1           12 System.Net.TimeoutValidator
  • 14ef9964        1           12 System.Net.Cache.HttpRequestCacheLevel
  • 14ef77a8        1           12 Microsoft.Win32.WinInetCache
  • 14ef68e4        1           12 System.Net.WebRequest+WebProxyWrapper
  • 14ef658c        1           12 System.Net.Configuration.ProxyElement+BypassOnLocalValues
  • 14ef63d8        1           12 System.Net.Configuration.ProxyElement+AutoDetectValues
  • 14ef5b68        1           12 System.Net.CaseInsensitiveAscii
  • 14ef5610        1           12 System.Net.HeaderInfoTable
  • 14ef4718        1           12 System.Net.HttpRequestCreator
  • 14db6710        1           12 System.Web.Configuration.MachineKeyValidationConverter
  • 14db3140        1           12 System.Collections.Generic.ObjectEqualityComparer`1[[System.Runtime.Serialization.MemberHolder, mscorlib]]
  • 14b3f4d8        1           12 System.Web.UI.SupportsEventValidationAttribute
  • ...etc...
  • 14a276a8    19578       704808 System.DirectoryServices.Interop.AdsValueHelper
  • 14a2ea24     9196       735680 System.Web.UI.WebControls.Label
  • 14a2e51c    16862       741928 System.Web.UI.WebControls.Style
  • 125778ec    48015       768240 System.Collections.Specialized.NameObjectCollectionBase+NameObjectEntry
  • 120261c8    65842       790104 System.Boolean
  • 14a2ee7c     9198       809424 System.Web.UI.WebControls.Table
  • 14b311c4     9647       810348 System.Web.UI.WebControls.Image
  • 13a2b7dc    34913       837912 System.Web.HttpServerVarsCollectionEntry
  • 14b303a4    10605       848400 System.Web.UI.WebControls.HyperLink
  • 14d8e3d4    77748       932976 Microsoft.Web.UI.WebControls.BaseChildNodeCollection+ActionType
  • 14db90ac    81372       976464 System.Web.UI.WebControls.FontInfo
  • 14b30694    28648      1031328 System.Web.UI.WebControls.TableRow+CellControlCollection
  • 14d8fdbc    38912      1089536 Microsoft.Web.UI.WebControls.TreeNodeCollection
  • 14b3d0bc    86592      1385472 System.Web.UI.Pair
  • 1466c5c4    39305      1414980 System.Web.UI.ControlCollection
  • 14d8e48c    77748      1865952 Microsoft.Web.UI.WebControls.BaseChildNodeCollection+Action
  • 1545061c    38874      2176944 Microsoft.Web.UI.WebControls.TreeNode
  • 14b30eec    52668      2317392 System.Web.UI.WebControls.TableItemStyle
  • 14a2f804    28515      2395260 System.Web.UI.WebControls.TableRow
  • 14a2be6c    40894      2453640 System.Web.UI.LiteralControl
  • 0fd3da00   228792      2745504 System.Int32
  • 14b3e3ac   244793      2937516 System.Web.UI.IndexedString
  • 14a2de94   198580      3177280 System.Web.UI.StateBag
  • 1466c454    80512      3542528 System.Web.UI.Control+OccasionalFields
  • 12302c2c   205849      4116980 System.Collections.Specialized.HybridDictionary
  • 14b30024    52934      4446456 System.Web.UI.WebControls.TableCell
  • 12302f2c   178294      4992232 System.Collections.Specialized.ListDictionary
  • 14a2e284   412762      6604192 System.Web.UI.StateItem
  • 14d8ce64   117078      7024680 Microsoft.Web.UI.WebControls.CssCollection
  • 0fd314bc   132065      7395640 System.Collections.Hashtable
  • 1230319c   422580      8451600 System.Collections.Specialized.ListDictionary+DictionaryNode
  • 1202a58c   380438      9130512 System.Collections.ArrayList
  • 0fd32050   133000     22582944 System.Collections.Hashtable+bucket[]
  • 02c3896c   649842     23275900 System.Object[]
  • 0fd3c12c     3471     36385536 System.Byte[]
  • 001fee20      338     65409920      Free
  • 02c39310   683083    161821000 System.String
  • Total 5515837 objects
  • Fragmented blocks larger than 0.5 MB:
  •     Addr     Size      Followed by
  • 2adf31cc    2.0MB         2aff85d8 System.String
  • 2b006a2c   20.3MB         2c4530d8 System.Net.SocketAddress

输出信息按对象类型的总大小升序排序,你一般可以在列表的最下面找到string对象的大小,因为字符串在程序中一般是最常用的。 其他比较有用的参数是-type和-mt(MethodTable的意思)。使用它们你可以查看指定对象类型的详细信息,例如假如我们想查看System.Net.HttpRequestCreator类型的具体信息,可以复制上面列表中它的MT字段地址(14ef4718),然后使用 !dumpheap -mt命令:

  • 0:050> !dumpheap -mt 14ef4718
  • ------------------------------
  • Heap 0
  • Address MT Size
  • 0342ccf8 14ef4718 12
  • total 1 objects
  • ------------------------------
  • Heap 1
  • Address MT Size
  • total 0 objects
  • ------------------------------
  • total 1 objects
  • Statistics:
  • MT Count TotalSize Class Name
  • 14ef4718 1 12 System.Net.HttpRequestCreator

上面列出了所有System.Net.HttpRequestCreator类型的对象的地址,假如我们想查看指定对象的信息,再使用!dumpobject命令就可以了。 !dumpheap -type可以根据字符串来匹配对应的对象类型。如我们输入命令“!dumpheap -type System.Web”,是指显示所有类名包含有“System.Web”字符串的对象信息。 其他参数-min和-max是接受表示对象大小的最大值和最小值(单位字节),命令会只列出大于指定值或小于指定值的对象信息。这两个参数对于查找滥用字符串问题很有帮助。

实战训练

查明缓存使用的大小

为了知道在System.Web.Caching.Cache类型中有多少数据,我执行了“ !dumpheap -stat -type System.Web.Caching.Cache”命令。注意,我用了-stat参数,否则我会得到一个包含有System.Web.Caching.CacheKeys和System.Web.Caching.CacheEntrys对象的很长的列表。下面的执行结果:

  • 0:050> !dumpheap -type System.Web.Caching.Cache -stat
  • ------------------------------
  • Heap 0
  • total 665 objects
  • ------------------------------
  • Heap 1
  • total 1084 objects
  • ------------------------------
  • total 1749 objects
  • Statistics:
  • MT Count TotalSize Class Name
  • 123056f8 1 12 System.Web.Caching.CacheKeyComparer
  • 1230494c 1 12 System.Web.Caching.Cache
  • 1230500c 1 24 System.Web.Caching.CacheMultiple
  • 1230514c 1 32 System.Web.Caching.CacheMemoryStats
  • 123053b4 1 36 System.Web.Caching.CacheMemoryTotalMemoryPressure
  • 123059bc 2 40 System.Web.Caching.CacheUsage
  • 12304bdc 1 48 System.Web.Caching.CacheCommon
  • 123054f4 1 52 System.Web.Caching.CacheMemoryPrivateBytesPressure
  • 12305874 2 64 System.Web.Caching.CacheExpires
  • 12304e64 2 200 System.Web.Caching.CacheSingle
  • 1255b594 85 1360 System.Web.Caching.CacheDependency+DepFileInfo
  • 123046c4 40 1440 System.Web.Caching.CacheDependency
  • 123042ec 47 1504 System.Web.Caching.CacheItemRemovedCallback
  • 123063fc 832 16640 System.Web.Caching.CacheKey
  • 12306820 732 52704 System.Web.Caching.CacheEntry
  • Total 1749 objects

很明显System.Web.Caching.Cache的方法列表地址(MethodTable)是1230494c,再使用!dumpheap命令我就能看到它的所有对象信息,如下:

  • 0:050> !dumpheap -mt 1230494c
  • ------------------------------
  • Heap 0
  • Address MT Size
  • 03392d20 1230494c 12
  • total 1 objects
  • ------------------------------
  • Heap 1
  • Address MT Size
  • total 0 objects
  • ------------------------------
  • total 1 objects
  • Statistics:
  • MT Count TotalSize Class Name
  • 1230494c 1 12 System.Web.Caching.Cache
  • Total 1 objects

可以看到System.Web.Caching.Cache类型只有一个对象,地址是03392d20,再通过!objsize命令就能计算出它的大小。因为缓存对象很复杂,并包含有大量的子对象,要计算出总大小需要花些时间:

  • 0:050> !objsize 03392d20
  • sizeof(03392d20) = 266640828 ( 0xfe49dbc) bytes (System.Web.Caching.Cache)

所以缓存的总大小是 266 MB。

缓存了什么东西?

为了弄清缓存中保存了什么内容,我查看了System.Web.Caching.CacheEntry的对象信息。通过之前的信息可以知道System.Web.Caching.CacheEntry类型的方法列表(MethodTable)是12306820。执行!dumpheap命令取CacheEntry的所有对象信息:

  • 0:050> !dumpheap -mt 12306820
  • ------------------------------
  • Heap 0
  • Address MT Size
  • 033950bc 12306820 72
  • 033a20d8 12306820 72
  • 033ac79c 12306820 72
  • 033da21c 12306820 72
  • 033f04c4 12306820 72
  • 03428ec8 12306820 72
  • 0344dab4 12306820 72
  • 03815d00 12306820 72
  • 038265d8 12306820 72
  • ....etc...
  • 03af7010 12306820 72
  • 03b291bc 12306820 72
  • 03b2c674 12306820 72
  • 03b6dca0 12306820 72
  • 03b797dc 12306820 72
  • 03b85318 12306820 72
  • 03ba9150 12306820 72
  • 03c258cc 12306820 72
  • 03de43c8 12306820 72
  • 03e160f8 12306820 72
  • total 382 objects
  • ------------------------------
  • total 732 objects

要显示上面的信息,也可以使用“!dumpheap -type System.Web.Caching.CacheEntry”命令。 有了所有CacheEntry对象的地址信息,我随机拿了一个地址查看它的内容:

  • 0:050> !do 03b2c674
  • Name: System.Web.Caching.CacheEntry
  • MethodTable: 12306820
  • EEClass: 122f6470
  • Size: 72(0x48) bytes
  • (C:\WINDOWS\assembly\GAC_32\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll)
  • Fields:
  • MT Field Offset Type VT Attr Value Name
  • 02c39310 4001327 4 System.String 0 instance 03b2c600 _key
  • 0fb8f1f8 4001328 c System.Byte 0 instance 2 _bits
  • 0fd3da00 4001329 8 System.Int32 0 instance -1314181915 _hashCode
  • 02c36ca0 4001330 10 System.Object 0 instance 03b2c644 _value
  • 120219d0 4001331 1c System.DateTime 1 instance 03b2c690 _utcCreated
  • 120219d0 4001332 24 System.DateTime 1 instance 03b2c698 _utcExpires
  • 1202af88 4001333 2c System.TimeSpan 1 instance 03b2c6a0 _slidingExpiration
  • 0fb8f1f8 4001334 d System.Byte 0 instance 7 _expiresBucket
  • 123062d8 4001335 34 ...g.ExpiresEntryRef 1 instance 03b2c6a8 _expiresEntryRef
  • 0fb8f1f8 4001336 e System.Byte 0 instance 4294967295 _usageBucket
  • 12306738 4001337 38 ...ing.UsageEntryRef 1 instance 03b2c6ac _usageEntryRef
  • 120219d0 4001338 3c System.DateTime 1 instance 03b2c6b0 _utcLastUpdate
  • 123046c4 4001339 14 ...g.CacheDependency 0 instance 00000000 _dependency
  • 02c36ca0 400133a 18 System.Object 0 instance 033d8344 _onRemovedTargets
  • 120219d0 400132d 1bc System.DateTime 1 shared static NoAbsoluteExpiration
  • >> Domain:Value 0019daf0:NotInit 11b42540:03395104 < <
  • 1202af88 400132e 1c0 System.TimeSpan 1 shared static NoSlidingExpiration
  • >> Domain:Value 0019daf0:NotInit 11b42540:03395114 < <
  • 1202af88 400132f 1c4 System.TimeSpan 1 shared static OneYear
  • >> Domain:Value 0019daf0:NotInit 11b42540:03395124 < <

输出的是CacheEntry的属性信息,里面最重要的是_value属性。我复制它的地址(03b2c644),再用!dumpobject命令查看:

  • 0:000> !do 03e160c8
  • Name: System.Web.SessionState.InProcSessionState
  • MethodTable: 14dbad5c
  • EEClass: 14e43af8
  • Size: 48(0x30) bytes
  • (C:\WINDOWS\assembly\GAC_32\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll)
  • Fields:
  • MT Field Offset Type VT Attr Value Name
  • 1466c9d8 4001d89 4 ...ateItemCollection 0 instance 1a7f5438 _sessionItems
  • 1292672c 4001d8a 8 ...ObjectsCollection 0 instance 00000000 _staticObjects
  • 0fd3da00 4001d8b c System.Int32 0 instance 20 _timeout
  • 120261c8 4001d8c 18 System.Boolean 0 instance 0 _locked
  • 120219d0 4001d8d 1c System.DateTime 1 instance 03e160e4 _utcLockDate
  • 0fd3da00 4001d8e 10 System.Int32 0 instance 1 _lockCookie
  • 1202bf60 4001d8f 24 ...ReadWriteSpinLock 1 instance 03e160ec _spinLock
  • 0fd3da00 4001d90 14 System.Int32 0 instance 0 _flags

可以看到缓存的是一个InProcSessionState对象。

CDSY,CDSY.XYZ
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐