SOS 调试扩展 (SOS.dll) 《第五篇》
一、SOS扩展命令
SOS包含几十个命令,要熟练使用SOS,首先要了解SOS有哪些命令。下面给出SOS命令列表。
命令 | 描述 |
---|---|
BPMD [<module name> <method name>] [-md <MethodDesc>] |
建立一个断点在指定模块的指定方法上。 如果指定模块和方法尚未被载入,该命令等到该模块被载入并且被即时(just-in-time)编译的通知后再建立断点。 |
CLRStack [-a] [-l] [-p] |
只提供托管代码的栈跟踪。 -p 选项显示托管函数的参数。 -l 选项显示在一个框架里局部变量的信息。SOS调试扩展无法检索局部变量的名字,所以局部变量的输出格式为<local address> = <value>。 -a (all) 选项是-l和-p组合的快捷方式。 在x64和基于IA-64的平台上,SOS调试扩展不显示过渡框架(Transition Frames)。 |
COMState |
列出每个线程COM单元模型和可用的上下文指针。 |
DumpArray [-start <startIndex>] [-length <length>] [-details] [-nofields] <array object address> -或者- DA [-start <startIndex>] [-length<length>] [-detail] [-nofields] <array object address> |
检查一个数组对象的元素。 -start 选项指定显示元素的起始索引号。 -length 选项指定要显示的元素数目。 -detail 选项按照DumpObj和DumpVC格式显示元素的细节。 -nofields 选项使数组显示不包括字段。仅当指定 -detail 选项时该选项才可用。 |
DumpAssembly <Assembly address> |
显示一个汇编集的有关信息。 如果存在多个模块,DumpAssembly命令将它们全部列出。 你可以用DumpDomain命令得到汇编集地址。 |
DumpClass <EEClass address> |
显示与一个类型相关的EEClass结构这些信息。 DumpClass命令显示静态字段值而不显示非静态字段值。 使用DumpMT、DumpObj、Name2EE、或Token2EE命令来获取一个EEClass结构地址。 |
DumpDomain [<Domain address>] |
枚举在指定AppDomain对象地址里面装载的每一个Assembly对象。当不带参数调用DumpDomain命令时,它列出一个进程中所有的AppDomain对象。 |
DumpHeap [-stat] [-min <size>][-max <size>] [-thinlock] [-mt<MethodTable address>] [-type<partial type name>][start [end]] |
显示关于垃圾收集堆的信息和有关对象的收集统计。 DumpHeap命令如果在垃圾收集器堆中检测到过多的碎片,它显示一个警告。 -stat 选项限制输出内容只有统计的类型摘要。 -min 选项忽略那些尺寸小于size参数的对象,以字节为单位。 -max 选项忽略那些尺寸大于size参数的对象,以字节为单位。 -thinlock 选项报告ThinLocks。更多信息请看SyncBlk命令。 -mt 选项只列出符合所指定MethodTable结构的那些对象。 -type 选项只列出类型名字子串匹配指定字符串的那些对象。 参数 start 指定开始列出的地址。 参数 end 指定停止列出的地址。 |
DumpIL [<DynamicMethod address>] [<DynamicMethodDesc address>] [<MethodDesc address>] |
显示与一个托管方法相关的中间语言(IL)。 注意,动态IL是发射来的(emitted),不同于从一个汇编集装载的IL。动态IL引用一个托管对象数组中的对象,而不是通过元数据标记引用对象。 |
DumpLog [<Filename>] |
把一个内存里的重要日志的内容写入指定文件。如果你没有指定文件名,该命令在当前目录中创建一个名为Stresslog.txt的文件。 公共语言运行时提供一个内存里的重要日志,帮助你诊断重要失败。日志使你可以不使用锁或I/O就能诊断失败。若要启用重要日志,需要在HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework下面设置以下注册表项: (DWORD) StressLog = 1 (DWORD) LogFacility = 0xffffffff (DWORD) StressLogSize = 65536 |
DumpMD <MethodDesc address> |
显示的信息是在指定地址上的一个MethodDesc结构。 你可以用IP2MD命令得到一个托管函数的MethodDesc结构地址。 |
DumpMT [-MD] <MethodTable address> |
显示在指定地址上的一个方法表的有关信息。指定 -MD 选项显示列出该对象定义的所有方法。 每个托管对象包含有一个方法表指针。 |
DumpMethodSig <sigaddr> <moduleaddr> |
显示在指定地址上的一个MethodSig结构的有关信息。 |
DumpModule [-mt] <Module address> |
显示在指定地址上的一个模块的有关信息。-mt 选项显示在该模块中所定义的类型和被该模块引用的类型。 你可以用DumpDomain或DumpAssembly命令检索一个模块的地址。 |
DumpObj <object address> -或者- DO <object address> |
显示在指定地址上的一个对象的有关信息。DumpObj命令显示字段、EEClass结构信息、方法表和该对象的尺寸。 你可以用DumpStackObjects命令检索一个对象的地址。 注意,因为类型CLASS的字段也是对象,所以你可以对它们执行DumpObj命令。 |
DumpRuntimeTypes |
显示在垃圾收集器堆中的运行时类型对象,并列出与它们相关的类型名字和方法表。 |
DumpStack [-EE] [top stack [bottom stack]] |
显示一个栈跟踪(回溯)。 -EE 选项使DumpStack命令只显示托管函数。在x86平台上使用top和bottom参数限制所显示的栈框架。 在x86平台上,DumpStack命令创建一个冗长的栈跟踪。 在x64和基于IA-64的平台上,DumpStack命令模仿调试器的 K 命令。在x64和基于IA-64的平台上top和bottom参数被忽略。 |
DumpSig <sigaddr> <moduleaddr> |
显示在指定地址上的一个Sig结构的有关信息。 |
DumpStackObjects [-verify] [top stack [bottom stack]] -或者- DSO [-verify] [top stack [bottom stack]] |
显示在当前栈范围内找到的所有托管对象。 -verify 选项验证对象字段的每一个非静态CLASS字段。 带有栈跟踪命令使用DumpStackObject命令,比如 K 命令和CLRStack命令确定局部变量和参数的值。 |
DumpVC <MethodTable address> <Address> |
显示在指定地址上的一个值类的字段信息。 MethodTable参数使DumpVC命令能够正确地解释字段。值类不以方法表作为它们的第一个字段。 |
EEHeap [-gc] [-loader] |
显示被公共语言运行时内部数据结构使用的进程内存的有关信息。 -gc 和 -loader 选项限制该命令的输出内容为垃圾收集器或者装载器的数据结构。 对于垃圾收集器,列出在托管堆里每一个节的范围信息。如果某指针是在EEHeap -gc给出的某个节范围内,那么该指针是一个对象指针。 |
EEStack [-short] [-EE] |
对进程中所有线程执行DumpStack命令。 -EE 选项被直接传递给DumpStack命令。-short 参数限制输入内容为以下线程种类:
|
EEVersion |
显示公共语言运行时版本。 |
EHInfo [<MethodDesc address>] [<Code address>] |
显示所指定方法里的异常处理块。这个命令显示子句块(try块)和处理者块(catch块)的代码地址及偏移量。 |
FinalizeQueue [-detail] |
显示为终结(finalization)而登记的所有对象。 -detail 选项显示关于等待清除的任何SyncBlocks的附加信息和等待清除的任何RuntimeCallableWrappers (RCWs) 的额外信息。两个数据结构都是由终结器(finalizer)线程缓存和清除。 |
FindAppDomain <Object address> |
确定在指定地址上的一个对象的应用程序域。 |
GCHandles [-perdomain] |
显示在进程中垃圾收集器句柄的统计。 如果传递-perdomain 选项,则按照应用程序域顺序排列统计。 使用GCHandles命令查找由垃圾收集器句柄泄漏引起的内存泄漏。例如,由于一个强健的垃圾收集器句柄指向代码的一个大数组成部分,而该句柄没有被释放就丢弃了,所以代码实际上还保留着这个数组,这时就出现一个内存泄漏。 |
GCHandleLeaks |
在内存里搜索进程中对那些强健而且有麻烦的垃圾收集器句柄的任何引用,并且显示结果。如果找到某个句柄,GCHandleLeaks命令显示该引用的地址。如果在内存里没有找到某个句柄,这个命令显示一个通知。 |
GCInfo <MethodDesc address><Code address> |
显示数据指示何时寄存器或栈位置包含有托管对象。如果发生垃圾收集,收集器必须知道指向对象的引用的位置,如此它才可以用新的对象指针值更新它们。 |
GCRoot [-nostacks] <Object address> |
显示对在指定地址上的一个对象的引用(或根)信息。 GCRoot命令检查整个托管堆和在栈以及其他对象里面句柄的句柄表。然后,在每个栈和终结器队列中搜索指向对象的指针。 这个命令不确定一个栈根是有效的还是已丢弃的。为了确定栈根是否还在使用中,需要用CLRStack和U命令反汇编局部变量或参数值所属的框架。 -nostacks 选项限制只搜索垃圾收集器句柄和终结器队列里的对象(freachable objects)。 |
help [<command>] [<faq>] |
当没有指定参数时显示所有可用命令,或者当指定命令为参数时显示其详细帮助信息。 faq 参数显示常问问题的答案。 |
IP2MD <Code address> |
显示在已经即时编译(JIT)的代码里指定地址上的MethodDesc结构。 |
MinidumpMode [0] [1] |
防止在使用一个小转储(minidump)时执行非安全命令。 传递 0 以禁用这个功能,或传递 1 以启用这个功能。默认地,MinidumpMode把值设置为 0 。 用 .dump /m 命令或者 .dump 命令创建的小转储已经限制为特定的CLR数据,并且让你只可以正确地运行SOS命令的一个子集。有些命令可能因不可预见的错误而失败,因为所必需的内存区域没有被映射或者只有部分被映射。这个选项让你避免对小转储执行非安全命令。 |
Name2EE <module name> <type or method name> -或者- Name2EE <module name>!<type or method name> |
显示指定模块中指定类型或方法的MethodTable结构和EEClass结构。 指定模块必须被装入进程中。 可以使用MSIL反汇编器 (Ildasm.exe) 浏览模块,以取得适当的类型名字。你也可以传递 * 作为模块名字参数以搜索所有装入的托管模块。模块名字参数也可以是调试器给一个模块的名字,比如mscorlib或image00400000。 这个命令支持Windows调试器句法<module>!<type>。该类型必须被完全限定。 |
ObjSize [<Object address>] |
显示指定对象的尺寸。若不带参数,则ObjSize命令显示在托管线程中找到的全部对象的尺寸,显示进程中全部的垃圾收集器句柄,并求出指向那些句柄的所有对象的尺寸总和。ObjSize命令把父对象全部子对象的尺寸也计算在内。 |
PrintException [-nested] [<Exception object address>] -或者- PE [-nested] [<Exception object address>] |
编排格式并显示在指定地址上的任何Exception类派生对象的字段。如果你没有指定一个地址,PrintException命令显示当前线程上最近抛出的异常。 -nested 选项详细显示嵌套的异常对象。 你可以使用这个命令编排格式并查看_stackTrace字段,这是一个二元数组。 |
ProcInfo [-env] [-time] [-mem] |
显示针对该进程的环境变量、内核CPU时间和内存使用统计。 |
RCWCleanupList<RCWCleanupList address> |
显示在指定地址上的正等待清除的运行时可调用的包裹器列表。 |
SaveModule <Base address> <Filename> |
把装入在指定地址上的一个内存映像写入指定文件。 |
StopOnException [-derived] [-create | -create2] <Exception> <Pseudo-register number> |
使调试器当指定异常被抛出时停止,而当其他异常被抛出时则继续运行。 -derived 选项捕获指定异常及其衍生的每个异常。 |
SyncBlk [-all | <syncblk number>] |
显示指定的SyncBlock结构或者所有的SyncBlock结构。如果你没有传递任何参数,SyncBlk命令显示一个线程所有对象相应的SyncBlock结构。 一个SyncBlock结构是一个附加信息的容器,不必为每个对象创建它。它能够容纳COM互用数据、散列码、和用于线程-安全操作的锁定信息。 |
ThreadPool |
显示托管线程池的有关信息,包括在队列中工作请求的数目、完全端口线程的数目、和计时器数目。 |
Token2EE <module name> <token> |
把指定模块中指定的元数据标记转换成一个MethodTable结构或者MethodDesc结构。 你也可以把 * 作为模块名字参数,以使在每个被载入的托管模块中找出该标记的映射目标。模块名字参数也可以是调试器给一个模块的名字,比如mscorlib 或 image00400000 。 |
Threads [-live] [-special] |
显示进程中所有的托管线程。 Threads命令显示 调试器简写ID号、公共语言运行时线程ID号、和正在操作中的系统线程ID号。此外,Threads命令显示 一个Domain栏指示线程运行所处在的应用程序域、一个APT栏显示COM单元的模式、和一个Exception栏显示线程最近抛出的异常。 -live 选项显示与某个活线程有关联的那些线程。 -special 选项显示CLR创建的所有特别线程。特别线程包括(并发GC和服务器GC中的)垃圾收集(GC)线程、调试器助手线程、Finalizer线程、AppDomain卸载线程、和线程池计时器线程。 |
TraverseHeap [-xml] <filename> |
遵照CLR简档器隐含的格式把堆信息写入到指定文件。-xml选项使TraverseHeap命令把该文件格式化为XML。 |
U [-gcinfo] [-ehinfo] <MethodDesc address> | <Code address> |
通过指定一个指向某个方法MethodDesc结构的指针或者指定其方法体里面的一个代码地址,显示一个托管方法有注释的反汇编。U命令显示整个方法,从开始到完成,并在注释里把元数据标记转换为名字。 -gcinfo 选项使U命令显示这个方法使用的GCInfo结构。 -ehinfo 选项显示这个方法的异常信息。你也可以用EHInfo命令来获取该信息。 |
VerifyHeap |
检查垃圾收集器堆的崩溃标志,显示发现的任何错误。 堆崩溃能够由不正确地构成的平台援用(platform invoke)调用引起。 |
VMMap |
横跨虚拟地址空间,显示加诸每区域的保护类型。 |
VMStat |
按照加诸内存的保护类型(自由的free、保留的reserved、约束的committed、私有的private、映射的mapped、映像image)顺序,提供虚拟地址空间的概览。TOTAL栏显示AVERAGE栏乘以BLK COUNT栏的结果。 |
二、加载SOS
SOS调试扩展让你可以查看在公共语言运行时里面运行的代码的有关信息。例如,你可以使用SOS调试扩展显示托管堆的有关信息,查找堆的错误,显示运行时使用的内部数据类型,以及查看在运行时里面运行的所有托管代码的有关信息。
在调试托管代码时,有两个扩展DLL需要注意,它们分别是SOS和SOSEX。
在使用SOS之前,第一步就是要加载SOS。
1、元命令loadby加载SOS
元命令loadby尝试找出由ModuleName指定的路径(通过查看进程中的已加载模块列表),并且使用这个路径来加载指定的DLLNAME(调试器扩展的DLL)。
如果mscorwks模块还没有被加载,那么元命令loadby将提示以下错误信息:
- 0:000> .loadby sos.dll mscorwks
- Unable to find module 'mscorwks'
在Windbg.exe中装载SOS的命令是:
- .loadby sos mscorwks
2、元命令load加载SOS
如果使用的.Net版本不同,那么还可以手动指定版本,如手动指定载入4.0版本命令:
- .load C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/sos.dll
.load C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/sos.dll
如果是64位,那么应该加载如下sos.dll
- .load C:/Windows/Microsoft.NET/Framework64/v2.0.50727/sos.dll
- .load C:/Windows/Microsoft.NET/Framework64/v2.0.50727/sos.dll
SOS.dll 随 .NET Framework 安装在 %windir%\microsoft.net\framework\<.NET 版本> 目录下。
3、加载mscordacwks.dll
在调试.Net程序时,调试器可以加载一个辅助DLL,称为mscordacwks.dll,这个DLL用于输出托管代码调试过程中的各种信息。加载mscordacwks.dll的路径取决于被加载到进程中的mscorwks.dll的路径。在实时调试中通常不存在问题,因为我们希望加载与已加载的mscorwks.dll相对应的mscordacwks.dll版本,但在事后调试中则可能出现版本不匹配的情况。要想控制调试行为,我们可以使用元命令,cordll,并控诉调试器加载mscordacwks.dll的确切位置。例如,如果要指定一个新路径,那么可以使用以下命令:
- .cordll -lp c:\x\y\z
这样便能告诉调试器从文件夹c:\x\y\z下加载mscordacwks.dll。如果要卸载mscordacwks.dll可以使用-u开关。
三、内存转储
在调试器中有许多命令都可以用来转储内存的内容。内存转储通常用于查看内存中的对象。最常用的命令是d(表示内存)。命令d的最简单形式只带有一个参数,表示需要显示的内存地址。命令d能够以非常简洁的形式显示需要查看的内存。
- dd:直接显示内存;
- du:把被转储的内存视为Unicode字符;
- da:把被转储的内存视为ASCII字符;
- dw:把被转储的内存视为字(word);
- db:把被转储的内存视为字节值和ASCII字符;
- dq:把被转储的内存视为四字(quad word)值;
1、DumpObj 转储引用类型
DumpObj的缩写为dso。要判断一个指针指向的是否是值类型,最佳方式就是使用DumpObj命令,但它只对引用类型有效。DumpObj命令的参数是一个指向引用类型的指针,能输出这个引用类型的内容。如果给定的指针指向一个值类型,那么DumpObj命令会给出以下错误提示:
- 0:000> !DumpObj 0x002bf0b4
- <Note: this object has an invalid CLASS field>
- Invalid object
DumpObj详细介绍:
- 0:083> !do 00000002838d92c8
- Name: System.String
- MethodTable: 000007fef0667d90
- EEClass: 000007fef026e560
- Size: 411932(0x6491c) bytes
- (C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
- String: 粤A87xxx,粤ACxxx挂......
- Fields:
- MT Field Offset Type VT Attr Value Name
- 000007fef066f000 4000096 8 System.Int32 1 instance 205954 m_arrayLength
- 000007fef066f000 4000097 c System.Int32 1 instance 205953 m_stringLength
- 000007fef06697d8 4000098 10 System.Char 1 instance 7ca4 m_firstChar
- 000007fef0667d90 4000099 20 System.String 0 shared static Empty
- >> Domain:Value 000000000112bef0:00000001ff350370 000000000372e6e0:00000001ff350370 <<
- 000007fef0669688 400009a 28 System.Char[] 0 shared static WhitespaceChars
- >> Domain:Value 000000000112bef0:00000001ff350b60 000000000372e6e0:00000001ff3588e8 <<
- Name:对象的类型。如上面是一个字符串。
- Size:对象的大小。如上面是411932 bytes。
- String:这个是对字符串类型的特别关照,可以看到内容。其他对象就不知道了。
- Fields:指向其他类型的引用
说明:
选项 | 说明 |
MT | 这个域的方法列表 |
Field | 这个域的元数据。高顺序位(4)表示它是一个域,而低顺序位(1)是在元数据表中的偏移。 |
Offset | 这个域在引用类型内存布局中的偏移。 |
Type | 这个类型的缩写名字。 |
VT | 如果被设置为1,那么表示这是一个值类型,如果为0,这表示是一个引用类型。 |
Attr | 对象的属性。 |
Value | 域的值。 |
Name | 域的名字。 |
2、DumpVC 转储值类型
DumpVC的唯一作用就是显示值类型,它能够转储引用类型里面的值类型。
它唯一的形式如下:
!DumpVC <MethodTable address> <Address>
在DumpObj命令的输出中可以很容易地得到"Method Table Address"和"Address"。Method Table Address就是do命令Fields下的MT列,Address就是Value列。
- 0:083> !DumpVC 907b50 67903084
- Not a managed object
- 0:083> !DumpVC 000007fef066f000 191394
- Name: System.Int32
- MethodTable 000007fef066f000
- EEClass: 000007fef0272088
- Size: 24(0x18) bytes
- (C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
- Fields:
- MT Field Offset Type VT Attr Value Name
- 000007fef066f000 4000411 0 System.Int32 1 instance m_value
3、!DumpStackObjects 当前线程对象分配过程
!DumpStackObjects 当前线程的对象分配过程。缩写形式为!dso。
- :> !dso
- OS Thread Id: 0x6914 ()
- RSP/REG Object Name
- 000000000b65c470 000000022f3cfe10 System.Web.HttpApplication+PipelineStepManager
- 000000000b65c8a8 00000002838d92c8 System.String
- 000000000b65ca10 000000014f620fe0 System.String
- 000000000b65ca18 00000002838d92c8 System.String
- 000000000b65ca20 000000014f621260 System.String
- 000000000b65ca38 000000022f3cfe10 System.Web.HttpApplication+PipelineStepManager
- 000000000b65ca98 000000022f3cfe10 System.Web.HttpApplication+PipelineStepManager
- 000000000b65caa0 000000022f3cfe10 System.Web.HttpApplication+PipelineStepManager
- 000000000b65cab0 00000001dfc47d28 System.String
- 000000000b65cab8 000000014f621260 System.String
- 000000000b65cad0 000000014f620fe0 System.String
- 000000000b65cb00 000000014f620fe0 System.String
- 000000000b65cb30 000000014f620fe0 System.String
- ...
4、ObjSize 查看对象大小
ObjSize 用于知道对象地址时,查看该对象的大小。
- 0:083> !ObjSize 00000001ff350370
- sizeof(00000001ff350370) = 32 ( 0x20) bytes (System.String)
5、DumpHeap
显示关于垃圾收集堆的信息和有关对象的收集统计。
- -stat 选项限制输出内容只有统计的类型摘要。
- -min 选项忽略那些尺寸小于size参数的对象,以字节为单位。
- -max 选项忽略那些尺寸大于size参数的对象,以字节为单位。
- -thinlock 选项报告ThinLocks。更多信息请看SyncBlk命令。
- -mt 选项只列出符合所指定MethodTable结构的那些对象。
- -type 选项只列出类型名字子串匹配指定字符串的那些对象。
- 参数 start 指定开始列出的地址。
- 参数 end 指定停止列出的地址。
!DumpHeap -type People :统计出含有类名中含有People的对象。
!DumpHeap -mt 79105cd4 : 根据MT结构查询详细信息。能够根据MT查询到Address以用于!do命令。
- 0:083> !DumpHeap -stat
- ------------------------------
- Heap 0
- total 140040 objects
- ------------------------------
- Heap 1
- total 108057 objects
- ------------------------------
- ...
- Heap 23
- total 73065 objects
- ------------------------------
- total 2737406 objects
- Statistics:
- MT Count TotalSize Class Name
- 000007ff00ff7140 1 24 Comit.TE.Web.Areas.Management.Controllers.PrintProfilesController+PrintProfilesBrief[]
- ...
- 000007fef066f000 1170210 28085040 System.Int32
- 00000000010c12d0 228 32131528 Free
- 000007fef066f8b0 67392 46915920 System.Collections.Hashtable+bucket[]
- 000007fef0667d90 291003 96055608 System.String
- Total 2737406 objects
- Fragmented blocks larger than 0.5 MB:
- Addr Size Followed by
- 000000014f92ff10 4.2MB 000000014fd5c698 System.String
- 000000019fb89940 6.3MB 00000001a01d57b8 System.Threading.OverlappedData
- 000000020fb18698 5.7MB 00000002100ccc70 System.Threading.Overlapped
6、DumpArray
DumpArray用于转储数组。
- 0:000> !DumpArray 00000000ffb44c28
- Name: System.Object[]
- MethodTable: 000007fef0655b80
- EEClass: 000007fef026eb88
- Size: 96(0x60) bytes
- Array: Rank 1, Number of elements 8, Type CLASS
- Element Methodtable: 000007fef0667680
- [0] 00000000ff5dc768
- [1] 000000014f438e50
- [2] 00000000ffb44a50
- [3] 000000010f668698
- [4] 00000000ffb44c10
- [5] 00000000ffb44c88
- [6] null
- [7] null
[0]、[1]、[2]、[3]...就是值的地址,只要!do这个地址就能够查看了。
那么!DumpArray后面跟的地址又来自哪里呢?来自于!do命令的第一行Fields的Value:
!dumpheap -stat -> !dumpheap -mt MT列 -> !do Address列 -> !DumpArray Fields第一行Value列 -> !do[0][1][2]
- 0:000> !DumpObj 00000000ffb44be8
- Name: System.Collections.ArrayList
- MethodTable: 000007fef066ec78
- EEClass: 000007fef0271f10
- Size: 40(0x28) bytes
- (C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
- Fields:
- MT Field Offset Type VT Attr Value Name
- 000007fef0655b80 400094d 8 System.Object[] 0 instance 00000000ffb44c28 _items
- 000007fef066f000 400094e 18 System.Int32 1 instance 6 _size
- 000007fef066f000 400094f 1c System.Int32 1 instance 6 _version
- 000007fef0667680 4000950 10 System.Object 0 instance 0000000000000000 _syncRoot
- 000007fef0655b80 4000951 388 System.Object[] 0 shared static emptyArray
- >> Domain:Value 000000000112bef0:00000001ff354350 000000000372e6e0:00000001ff35bc08 <<
7、FinalizeQueue [-detail]
已进入待终结Finalizer队列的对象。
- 0:083> !FinalizeQueue
- SyncBlocks to be cleaned up: 0
- MTA Interfaces to be released: 0
- STA Interfaces to be released: 0
- ----------------------------------
- ------------------------------
- Heap 0
- generation 0 has 3 finalizable objects (000000002e188cf0->000000002e188d08)
- generation 1 has 46 finalizable objects (000000002e188b80->000000002e188cf0)
- generation 2 has 4448 finalizable objects (000000002e180080->000000002e188b80)
- Ready for finalization 0 objects (000000002e188d08->000000002e188d08)
- ------------------------------
- ...
- Heap 23
- generation 0 has 2963 finalizable objects (00000000329be080->00000000329c3d18)
- generation 1 has 0 finalizable objects (00000000329be080->00000000329be080)
- generation 2 has 0 finalizable objects (00000000329be080->00000000329be080)
- Ready for finalization 0 objects (00000000329c3d18->00000000329c3d18)
- Statistics:
- MT Count TotalSize Class Name
- 000007fef0681898 1 24 System.Threading.OverlappedDataCache
- ...
- 000007fef0690639 8779 632088 UNKNOWN
- 000007fef065f2a9 40751 1304032 UNKNOWN
- 000007fef065f2a8 41408 1325056 System.WeakReference
- Total 92039 objects
四、线程
1、ThreadPool 线程池相关信息
显示托管线程池的有关信息,包括在队列中工作请求的数目、完全端口线程的数目、和计时器数目。
- 0:083> !ThreadPool
- CPU utilization 81%
- Worker Thread: Total: 24 Running: 21 Idle: 3 MaxLimit: 2147483647 MinLimit: 24
- Work Request in Queue: 45
- AsyncTimerCallbackCompletion TimerInfo@000000001043dee0
- AsyncTimerCallbackCompletion TimerInfo@000000001043dee0
- ...
- AsyncTimerCallbackCompletion TimerInfo@00000000108d4140
- AsyncTimerCallbackCompletion TimerInfo@00000000108c9c20
- --------------------------------------
- Number of Timers: 55
- --------------------------------------
- Completion Port Thread:Total: 1 Free: 1 MaxFree: 48 CurrentLimit: 0 MaxLimit: 2147483647 MinLimit: 24
CPU utilization:占用CPU百分比;
Worker Thread: 工作线程统计:
- Total: 工作线程总数;
- Running:正在运行的工作线程数;
- Idle:空转线程数;
- MaxLimit:最大允许运行的线程数;
- MinLimit:最小允许运行的线程数;
- Number of Timers:计时器数量;
Completion Port Thread:I/O线程数统计:
- Total:I/O线程总数;
- Free:空闲I/O线程数;
- MaxFree:最大空闲I/O线程数;
- CurrentLimit: 当前I/O限制数;
- MaxLimit:最大I/O线程数限制;
- MinLimit:最小I/O线程数限制;
2、Threads [-live] [-special]
显示进程中所有的托管线程。
- 0:083> !Threads -special
- ThreadCount: 32
- UnstartedThread: 0
- BackgroundThread: 32
- PendingThread: 0
- DeadThread: 0
- Hosted Runtime: no
- PreEmptive Lock
- ID OSID ThreadOBJ State GC GC Alloc Context Domain Count APT Exception
- 61 2 a8a0 00000000036eeb30 b220 Enabled 0000000000000000:0000000000000000 000000000112bef0 0 MTA (Finalizer)
- ...
- OSID Special thread type
- 35 59f8 IOCompletion
- 36 7f2c DbgHelper
- 37 eb0 GC SuspendEE
- 60 19d0 GC
- 61 a8a0 Finalizer
- 62 547c Timer
- 63 8c2c ADUnloadHelper
- 64 2fc ThreadpoolWorker
- 87 8ce4 ThreadpoolWorker
- ...
- -live:与或线程有关联的线程;
- -special:特殊线程列表:
- special命令非常有用,它能够帮助你分清楚某个线程是什么线程。
- Special thread type列有如下取值:
- GC:垃圾回收线程;
- Finalizer:对象释放线程,.Net至少有一个,用于专门处理对象释放。
- Timer:计时器线程;
- ThreadpoolWorker:工作者线程;
- IOCompletion:I/O线程;
- ADUnloadHelper:
- DbgHelper:
- GC SuspendEE:
3、clrstack [-a] [-l] [-p]
当前线程的托管代码调用堆栈。
- -p 显示托管函数的参数。
- -l 显示在一个框架里局部变量的信息。SOS调试扩展无法检索局部变量的名字,所以局部变量的输出格式为<local address> = <value>。
- -a (all) 选项是-l和-p组合的快捷方式。
- 0:083> !clrstack
- OS Thread Id: 0x6914 (83)
- Child-SP RetAddr Call Site
- 000000000b65cae0 000007ff00cf0313 System.String.Concat(System.String, System.String, System.String)
- 000000000b65cb40 000007ff012b0ac5 xx.TE.Web.Service.Management.CompositeFieldService.GetCompositeFieldContent(System.Web.HttpContextBase, System.String, Comit.TE.Web.Domain.Management.CompositeField, Int32)
- 000000000b65cfd0 000007ff0126d39b xx.TE.Web.Areas.Cases.Controllers.WritDataBagController.PageWritContent(System.String, Int32)
- 000000000b65d410 000007fee7ca082c DynamicClass.lambda_method(System.Runtime.CompilerServices.ExecutionScope, System.Web.Mvc.ControllerBase, System.Object[])
- 000000000b65d460 000007fee7ca31ef System.Web.Mvc.ReflectedActionDescriptor.Execute(System.Web.Mvc.ControllerContext, System.Collections.Generic.IDictionary`2<System.String,System.Object>)
- 000000000b65d4c0 000007fee7ca47b5 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(System.Web.Mvc.ControllerContext, System.Web.Mvc.ActionDescriptor, System.Collections.Generic.IDictionary`2<System.String,System.Object>)
- ...
这个命令是sos.dll的支持,如果希望显示当前线程的非托管代码调用堆栈,应该使用kb。
此处还有一种写法~*e!clrstack:此命令用于显示所有线程的托管代码调用堆栈。
4、DumpStack
!clrstack只显示托管代码,而!kb只显示非托管代码。而DumpStack则是以上两个命令的综合版。既显示托管代码堆栈也显示非托管代码堆栈。-EE 选项使DumpStack命令只显示托管函数。
- :> !dumpstack
- OS Thread Id: 0x6914 ()
- Child-SP RetAddr Call Site
- 000000000b65c468 000007fefd6d10dc ntdll!ZwWaitForSingleObject+0xa
- 000000000b65c470 000007fef128d0e0 KERNELBASE!WaitForSingleObjectEx+0x79
- 000000000b65c510 000007fef128d1e3 mscorwks!MethodTableBuilder::MethodSignature::GetMethodAttributes+0xa8
- 000000000b65c560 000007fef138e250 mscorwks!CLREvent::WaitEx+0x63
- 000000000b65c610 000007fef15a9596 mscorwks!SVR::gc_heap::wait_for_gc_done+0x80
- 000000000b65c650 000007fef17339cc mscorwks!SVR::GCHeap::GarbageCollectGeneration+0x206
- 000000000b65c6b0 000007fef13996a2 mscorwks!SVR::gc_heap::try_allocate_more_space+0x1ac
- 000000000b65c7a0 000007fef136ecef mscorwks!SVR::gc_heap::allocate_more_space+0x32
- 000000000b65c7f0 000007fef12d7278 mscorwks!SVR::gc_heap::allocate_large_object+0x5f
- 000000000b65c860 000007fef12d758e mscorwks!SVR::GCHeap::Alloc+0x198
- 000000000b65c8a0 000007fef17b9433 mscorwks!SlowAllocateString+0x7e
- 000000000b65c920 000007fef051beec mscorwks!FramedAllocateString+0xd3
- 000000000b65cae0 000007ff00cf0313 mscorlib_ni!System.String.Concat(System.String, System.String, System.String)+0x4c
- 000000000b65cb40 000007ff012b0ac5 xxx_TE_Web_Service!xxx.TE.Web.Service.Management.CompositeFieldService.GetCompositeFieldContent(System.Web.HttpContextBase, System.String, Comit.TE.Web.Domain.Management.CompositeField, Int32)+0x13d3
- 000000000b65cfd0 000007ff0126d39b xxx_TE_Web!xxx.TE.Web.Areas.Cases.Controllers.WritDataBagController.PageWritContent(System.String, Int32)+0x6a5
...
5、进程信息
在调试会话中,有时候获得关于被调试进程的更多信息是非常有用的。例如,内存使用量,环境变量,处理时间等,这些数据都是非常有用的。要在调试时将这些信息转储出来,可以使用ProInfo命令。语法如下:
- !ProcInfo [-env][-time][-mem]
其中-env、-time、-mem等开关控制着所要显示的进程信息。如果没有指定任何开关,那么会显示所有者三类信息。
在时候调试Dump File里面试不支持这个命令的。
- 0:000> !ProcInfo
- ---------------------------------------
- Environment
- =::=::\
- ALLUSERSPROFILE=C:\ProgramData
- ANALYSIS_PATH=D:\LoadRunner\
- APPDATA=C:\Users\ChenZhuo\AppData\Roaming
- ClassPath=.;%JAVE_HOME%lib/rt.jar;C:\Program Files\Java\jdk1.6.0_24lib/tools.jar
- CommonProgramFiles=C:\Program Files\Common Files
- COMPUTERNAME=CZZ
- ComSpec=C:\Windows\system32\cmd.exe
- CURR_DIR=D:\LoadRunner\dat\Setup\LoadRunner\MSBuild\..\..\..\..
- FP_NO_HOST_CHECK=NO
- FTP_PASSIVE=1
- HOMEDRIVE=C:
- HOMEPATH=\Users\ChenZhuo
- JAVA_HOME=C:\Program Files\Java\jdk1.6.0_24
- LG_PATH=D:\LoadRunner\
- LOCALAPPDATA=C:\Users\ChenZhuo\AppData\Local
- LOGGER_CONFIG_PATH=D:\LoadRunner\dat\ltlogconf.xml
- LOGONSERVER=\\CZZ
- LOG_FILE=C:\Users\ChenZhuo\AppData\Local\Temp\ihp_custom_batches.log
- LR_PATH=D:\LoadRunner\
- LR_ROOT=D:\LoadRunner\
- NUMBER_OF_PROCESSORS=4
- OS=Windows_NT
- Path=C:\Program Files\Debugging Tools for Windows (x86)\winext\arcade;%JAVA_HOME%/bin;c:\oracle\product\10.2.0\client_1\bin;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;...省略
- PROCESSOR_ARCHITECTURE=x86
- PROCESSOR_IDENTIFIER=x86 Family 6 Model 42 Stepping 7, GenuineIntel
- PROCESSOR_LEVEL=6
- PROCESSOR_REVISION=2a07
- ProgramData=C:\ProgramData
- ProgramFiles=C:\Program Files
- ---------------------------------------
- Process Times
- Process Started at: 2014 May 30 16:23:12.21
- Kernel CPU time : 0 days 00:00:00.01
- User CPU time : 0 days 00:00:00.01
- Total CPU time : 0 days 00:00:00.02
- ---------------------------------------
- Process Memory
- WorkingSetSize: 6820 KB PeakWorkingSetSize: 6820 KB
- VirtualSize: 97744 KB PeakVirtualSize: 98272 KB
- PagefileUsage: 6816 KB PeakPagefileUsage: 6824 KB
- ---------------------------------------
- 54 percent of memory is in use.
- Memory Availability (Numbers in MB)
- Total Avail
- Physical Memory 3486 1585
- Page File 4095 3019
- Virtual Memory 2047 1819
五、垃圾回收
1、GCRoot
!GCRoot是一个非常有用的命令,它能够帮助我们发现某对象上目前还存在的有效引用。这也是为什么GC还不回收这个对象的原因。这个信息可以很好的帮助我们分析那些本应该没有引用,但却一直还存在有效引用的对象,由此发现我们代码中潜在的内存泄漏,同时我们也可以观察到哪些对象是目前没有引用了。
- 0:000> !gcroot 000000011f993008
- Note: Roots found on stacks may be false positives. Run "!help gcroot" for
- more info.
- Scan Thread 22 OSTHread 3468
- Scan Thread 61 OSTHread a8a0
- Scan Thread 62 OSTHread 547c
- Scan Thread 63 OSTHread 8c2c
- Scan Thread 64 OSTHread 2fc
- Scan Thread 65 OSTHread 90a4
- RSP:aced0e8:Root:000000012f453b98(IBatisNet.DataMapper.MappedStatements.SelectMappedStatement)->
- 000000014f459390(IBatisNet.DataMapper.SqlMapper)->
- 000000014f459480(System.Collections.Specialized.HybridDictionary)->
- 000000014f5d8140(System.Collections.Hashtable)->
- 00000001ff6f5e38(System.Collections.Hashtable+bucket[])->
- 00000000ff5e7298(IBatisNet.DataMapper.Configuration.Cache.CacheModel)->
- 00000000ff5e7560(IBatisNet.DataMapper.Configuration.Cache.Memory.MemoryCacheControler)->
- 00000000ff5e75d8(System.Collections.Hashtable+SyncHashtable)->
- 00000000ff5e7580(System.Collections.Hashtable)->
- 000000028f350080(System.Collections.Hashtable+bucket[])->
- 000000011f992fd8(IBatisNet.DataMapper.Configuration.Cache.CacheKey)->
- 000000011f993008(System.Collections.ArrayList)
- Scan Thread 66 OSTHread 11d0
- Scan Thread 67 OSTHread 2928
- Scan Thread 68 OSTHread a2a4
- Scan Thread 69 OSTHread 2554
如上面能够查看到某对象被引用的关系。
六、其他
1、EEVersion
显示公共语言运行时版本。
- 0:061> !EEVersion
- 2.0.50727.5477 free
- Server mode with 24 gc heaps
- SOS Version: 2.0.50727.5477 retail build
上面的输出显示有24个GC堆(24核CPU),.Net版本为2.0.50727.5477。同时,该命令还输出了正在使用的SOS版本。
2、EEStack [-short] [-EE]
对进程中的所有线程执行DumpStack命令,-EE 选项被直接传递给DumpStack命令。-short 参数限制输入内容为以下线程种类:
已经被锁定的线程。
为了允许垃圾收集已经被迟延的线程。
目前处于托管代码中的线程。
- 0:083> !EEStack
- ---------------------------------------------
- Thread 22
- Child-SP RetAddr Call Site
- 000000000189fb88 000007fefd6d16ad ntdll!ZwRemoveIoCompletion+0xa
- 000000000189fb90 000000007750a4e1 KERNELBASE!GetQueuedCompletionStatus+0x39
- 000000000189fbf0 000007fef5701f7b kernel32!GetQueuedCompletionStatusStub+0x11
- 000000000189fc30 000007fef5702024 w3tp!THREAD_POOL_DATA::ThreadPoolThread+0x3b
- 000000000189fc80 000007fef57020a1 w3tp!THREAD_POOL_DATA::ThreadPoolThread+0x34
- 000000000189fcb0 000000007751652d w3tp!THREAD_MANAGER::ThreadManagerThread+0x61
- 000000000189fce0 000000007764c541 kernel32!BaseThreadInitThunk+0xd
- 000000000189fd10 0000000000000000 ntdll!RtlUserThreadStart+0x1d
- ---------------------------------------------
- Thread 61
- Child-SP RetAddr Call Site
- 000000000946f388 000007fefd6d10dc ntdll!ZwWaitForSingleObject+0xa
- 000000000946f390 000007fef128d0e0 KERNELBASE!WaitForSingleObjectEx+0x79
- 000000000946f430 000007fef128d1e3 mscorwks!MethodTableBuilder::MethodSignature::GetMethodAttributes+0xa8
- 000000000946f480 000007fef124bbf9 mscorwks!CLREvent::WaitEx+0x63
- 000000000946f530 000007fef124bd82 mscorwks!SVR::WaitForFinalizerEvent+0x49
- ...
SOS 调试扩展 (SOS.dll) 《第五篇》的更多相关文章
- SOS 调试扩展 (SOS.dll)
http://blog.csdn.net/cslie/article/details/2158780 SOS 调试扩展 (SOS.dll) 提供公共语言运行时(CLR)内部环境的有关信息,帮助你在Wi ...
- SOS.dll(SOS 调试扩展)
SecAnnotate.exe(.NET 安全批注器工具) SignTool.exe(签名工具) Sn.exe(强名称工具) SOS.dll(SOS 调试扩展) SqlMetal.exe(代码 ...
- VS2012中使用SOS调试CLR
之前看了<用WinDbg探索CLR世界>的一些列文章,发现SOS真的是一个非常好的调试.net的工具, 然后又惊喜的在http://blogs.msdn.com/b/marioheward ...
- 认识元数据和IL(下)<第五篇>
书接上回: 第二十四回:认识元数据和IL(上) , 第二十五回:认识元数据和IL(中) 我们继续. 终于到了,说说元数据和IL在JIT编译时的角色了,虽然两个回合的铺垫未免铺张,但是却丝毫不为过,因为 ...
- clr调试扩展和DAC
SOS.DLL.SOSEX.DLL这两个就是用来对.NET程序在Windows调试工具中起到翻译作用的调试器扩展.简单讲就是,这两个组件是.NET项目组专门开发出来用来对.NET应用程序进行方便调试用 ...
- 【Python五篇慢慢弹】快速上手学python
快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...
- 【Python五篇慢慢弹(5)】类的继承案例解析,python相关知识延伸
类的继承案例解析,python相关知识延伸 作者:白宁超 2016年10月10日22:36:57 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给 ...
- 第五篇 SQL Server代理理解代理错误日志
本篇文章是SQL Server代理系列的第五篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.在第四篇中我们看到 ...
- 【译】第五篇 SQL Server代理理解代理错误日志
本篇文章是SQL Server代理系列的第五篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.在第四篇中我们看到 ...
随机推荐
- DBA_在Linux上安装Oracle Database11g数据库(案例)
2014-08-08 Created By BaoXinjian
- HDU Count the string+Next数组测试函数
链接:http://www.cnblogs.com/jackge/archive/2013/04/20/3032942.html 题意:给定一字符串,求它所有的前缀出现的次数的和.这题很纠结,一开始不 ...
- [实变函数]4.2 Egrov 定理
1 一致收敛很重要, 但可惜的是很多时候不一致收敛. 比如 $$\bex f_n(x)=x^n\to f(x)=\sedd{\ba{ll} 0,&x\in [0,1)\\ 1,&x=1 ...
- H5与Native交互的实现
PDF文件下载:将后缀png改成PDF.
- bug_ _fragment的1
========= 2 fragment小结 ???? ======== 1 fragment:java.lang.IllegalStateException: Can not perf ...
- 如何开启ubuntu的SSH服务(不要和openssl搞混淆了)
ubuntu默认并没有安装ssh服务,如果通过ssh链接ubuntu,需要自己手动安装ssh-server,然而SSH分客户端openssh-client和服务端openssh-server,open ...
- Visual Studio 2015正式版/产品密钥 Win10正式版官方原版ISO镜像下载大全&安装激活教程
Visual Studio 2015 发行说明: https://visualstudio.com/zh-cn/news/vs2015-vs.aspx Visual Studio 2015 特性简 ...
- ArcGIS上根据经纬度求地球表面两点间距离的实现
ArcGIS上根据经纬度求地球表面两点间距离的实现 以米为单位..Net2.0,C#实现. public static double DistanceOfTwoPoints(double ...
- HDU 3068 [最长回文子串]
#include<iostream> #include<string> #include<string.h> #include<algorithm> # ...
- C++primer 练习15.26
定义Quote和Bulk_Quote的拷贝控制成员,令其与合成的版本行为一致.为这些成员以及其他构造函数添加打印状态的 语句,使得我们能够知道正在运行哪个程序.使用这些类编写程序,预测程序将创建和销毁 ...