第一章 准備
1.1. 環境配置
_NT_DEBUGGER_EXTENSION_PATH=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
_NT_SYMBOL_PATH=SRV*c:\Symbols*http://msdl.microsoft.com/download/symbols
Path add:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
C:\Program Files\Debugging Tools for Windows (x86)
1.2 .Net CLR知識
第二章 常用命令
2.1 基本命令
序號 |
命令 |
解釋 |
|
.chain |
顯示有哪些調試擴展。 |
|
.load DLLName !DLLName.load |
加載調試擴展。DLLName要是全路徑名,包括”.dll” |
|
.loadby DLLName ModuleName |
加載調試擴展。DLLName是短文件名,不包括”.dll”。 ModuleName是調試進程中的模塊名,表示通過它所在的路徑查找DLLName。 |
|
.unload DLLName !DLLName.unload |
卸載調試擴展。 |
|
.setdll DLLName !DLLName.setdll |
設置缺省的調試擴展。 |
|
![ext.]address |
顯示VM的分配狀況 |
|
![sos.]vmmap |
顯示VM的分配狀況 |
|
![uext.]vadump |
輸出虛擬地址映射信息 |
|
![uext.]vprot address |
顯示給出的虛擬地址所在內存的映射信息。 |
|
.logfle |
檢查是否有日志文件 |
|
.logopen .logappend |
打開日志文件。輸出內容多時特別有用! 一個是新建,另一個是追加。 |
|
.logclose |
關閉日志文件 |
|
dt |
通過符號輸出類型的結構拓撲信息。 |
|
![ntsdexts.]heap 0 0 |
察看Win32堆的運行狀況。 使用!heap –stat察看heap的內存使用情況。 |
|
![ext.]dlls |
可以察看進程內的動態鏈接庫的信息。 |
|
![sos.]threads |
可以列出所有的托管線程,並在棧頂給出異常對象的地址。 |
|
![sos.]ip2md addr |
可以將IP地址轉換成IL對應的方法名。 |
|
![sos.]BPMD <module name> <method name> ![sos.]BPMD -md <MethodDesc> |
可以在托管代碼的指定位置設置斷點。 method name是包含namespace.class.method的全名! !bpmd myapp.exe MyApp.Main Example for generics: Given the following two classes: class G3<T1, T2, T3> { ... public void F(T1 p1, T2 p2, T3 p3) { ... } } public class G1<T> { // static method static public void G<W>(W w) { ... } }
One would issue the following commands to set breapoints on G3.F() and G1.G():
!bpmd myapp.exe G3`3.F !bpmd myapp.exe G1`1.G |
|
![sos.]Name2EE module_name item_name ![sos.]Name2EE module_name!item_name |
查找名稱(類型/方法/屬性)對應的CLR信息 Examples: !Name2EE mscorlib.dll System.String.ToString !Name2EE *!System.String Examples: 0:018> !name2ee mscorlib.dll System.IntPtr Module: 790c2000 (mscorlib.dll) Token: 0x020000c1 MethodTable: 790fe160 EEClass: 790fe0d0 Name: System.IntPtr |
|
![sos.]dumpclass |
查找EEClass對應的信息 Examples: 0:018> !DumpClass 790fe0d0 Class Name: System.IntPtr mdToken: 020000c1 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) Parent Class: 790f9d24 Module: 790c2000 Method Table: 790fe160 Vtable Slots: 5 Total Method Slots: 1b Class Attributes: 102109 NumInstanceFields: 1 NumStaticFields: 1 MT Field Offset Type VT Attr Value Name 79118260 40003e0 4 PTR 0 instance m_value 790fe160 40003e1 96c System.IntPtr 0 shared static Zero >> Domain:Value 000da220:NotInit 000fde60:0 << |
|
![sos.]token2ee |
查找mdToken對應的名稱信息。 Examples: 0:018> !Token2EE mscorlib.dll 020000c1 Module: 790c2000 (mscorlib.dll) Token: 0x020000c1 MethodTable: 790fe160 EEClass: 790fe0d0 Name: System.IntPtr |
|
c rgBuf1 L 100 rgBuf2 |
比較內存 |
|
as |
設置別名,例: as Name EquivalentLine aS Name EquivalentPhrase aS Name "EquivalentPhrase" as /e Name EnvironmentVariable as /ma Name Address as /mu Name Address as /msa Name Address as /msu Name Address as /x Name Expression aS /f Name File as /c Name CommandString |
|
ad |
刪除別名,例: ad [/q] Name ad * |
|
al |
列表別名。例: al |
|
${ } |
解釋(提取)別名,例: Text ${Alias} Text Text ${/d:Alias} Text Text ${/f:Alias} Text Text ${/n:Alias} Text Text ${/v:Alias} Text |
|
特別有用的MASM命令處理函數. |
$fnsucc(FnAddress, RetVal, Flag) $iment (Address) $scmp("String1", "String2") $sicmp("String1", "String2") $spat("String", "Pattern") $vvalid(Address, Length) |
|
~#s |
設置當前線程上下文。例: 0: kd> ~1s 1: kd> |
|
$<, $><, $$<, $$><, $$>a< |
(Run Script File) $<Filename $><Filename $$< Filename $$>< Filename $$>a< Filename arg1 arg2 arg3 ... argn
|
|
!runaway |
The !runaway extension displays information about the time consumed by each thread. 查看線程信息 Flags Specifies the kind of information to be displayed. Flags can be any combination of the following bits. The default value is 0x1: Bit 0 (0x1) Causes the debugger to show the amount of user time consumed by each thread. Bit 1 (0x2) Causes the debugger to show the amount of kernel time consumed by each thread. Bit 2 (0x4) Causes the debugger to show the amount of time that has elapsed since each thread was created. 0:001> !runaway 7 例: User Mode Time Thread Time 0:55c 0:00:00.0093 1:1a4 0:00:00.0000
Kernel Mode Time Thread Time 0:55c 0:00:00.0140 1:1a4 0:00:00.0000
Elapsed Time Thread Time 0:55c 0:00:43.0533 1:1a4 0:00:25.0876 |
|
!envvar Variable |
獲取環境變量的值 0:000> !envvar _nt_symbol_path _nt_symbol_path = srv*C:\mysyms*http://msdl.microsoft.com/download/symbols |
|
.printf |
類似C庫的printf函數,可以接收的參數有: %p, %N, %I, %ma, %mu, %msa, %msu, %y, %ly 除了文檔中給出的參數,還可以接收C庫中的格式化字符串,如: %d, %c, %d, %f, %E等,功能強勁。 如果需要輸出64位數字,可以使用"%I64x"。如: 0:000> .printf "%I64x", 0x00001234`00000123; 123400000123 |
|
n [Radix] |
Set Number Base 命令格式: n [Radix] Radix Specifies the default number base that is used for numeric display and entry. You can use one of the following values. 8 Octal 10 Decimal 16 Hexadecimal |
|
![sos.]clrstack |
!CLRStack [-a] [-l] [-p] -a –l –p選項可以輸出棧的參數,非常有用! |
|
![sos.]DumpStack |
!DumpStack [-EE] [top stack [bottom stack]] 比ClrStack的輸出內容更為詳盡,能同時顯示native和.NET的堆棧信息!top stack/bottom stack是從k系列命令看到的棧頂和棧底地址。 -EE 限制只輸出.NET堆棧。 如: !DumpStack 77b1dae4 77b1dba4 |
|
![exts.]tp |
!tp pool Address [Flags] !tp tqueue Address [Flags] !tp ItemType Address [Flags] !tp ThreadType [Address] !tp -? 察看OS的thread pool信息 |
|
![sos.]threadpool |
察看.NET使用的thread pool的統計信息。 |
|
x |
x [Options] Module!Symbol x [Options] *!* 檢查加載的符號,特別有用! 注意,Module是模塊名,不帶.dll。例: 0:000> x mymodule!*spin* 0:000> x *!* |
|
j |
j (Execute If - Else) j Expression Command1 ; Command2 j Expression 'Command1' ; 'Command2' If this expression evaluates to a nonzero value, Command1 is executed. If this expression evaluates to zero, Command2 is executed.例: 0:000> bp `mysource.cpp:143` "j (poi(MyVar)>0n20) ''; 'gc' " 0:000> j (MySymbol=0) 'r eax'; 'r ebx; r ecx' 0:000> j (MySymbol=0) ''; 'r ebx; r ecx' 0:000> j (MySymbol=0) ; 'r ebx; r ecx' |
|
g gc |
如果在條件斷點之中,應使用gc命令,這樣如果通過step或trace進入斷點,那么出斷點gc維持step或trace命令;而g命令無論怎么進入斷點都使用g命令執行。 0:000> bp Address "j (Condition) 'OptionalCommands'; 'gc' " 0:000> bp Address "j (Condition) 'OptionalCommands'; 'g' " |
|
gu |
The gu command causes the target to execute until the current function is complete. User-Mode Syntax [~Thread] gu Kernel-Mode Syntax gu |
|
![sos.]findappdomain |
!findappdomain <object address> 查找對象所在的AppDomain |
|
sx, sxd, sxe, sxi, sxn, sxr |
sx, sxd, sxe, sxi, sxn, sxr (Set Exceptions) 設置異常發生后調試器的行為。 sx sx{e|d|i|n} [-c "Cmd1"] [-c2 "Cmd2"] [-h] {Exception|Event|*} sxr sx查看系統異常處理列表; sxr重置系統異常處理列表;
sxe Break (Enabled) When this exception occurs, the target immediately breaks into the debugger before any other error handlers are activated. This kind of handling is called first chance handling.
sxd Second chance break (Disabled). The debugger does not break for a first-chance exception of this type (although a message is displayed). If other error handlers do not address this exception, execution stops and the target breaks into the debugger. This kind of handling is called second chance handling.
sxn Output (Notify). When this exception occurs, the target application does not break into the debugger at all. However, a message is displayed that notifies the user of this exception.
sxi Ignore When this exception occurs, the target application does not break into the debugger at all, and no message is displayed. |
|
# |
# (Search for Disassembly Pattern) # [Pattern] [Address [ L Size ]] 示例: # mov 0040116b # 8945* 0040116b # 116d 0040116b # strlen main 例如:在反匯編“8b4510 mov eax,dword ptr [ebp+10h]”查找[ebp+10h],命令如下: # \[ebp\+10h\] 7c810000 注意,這個命令進行的是形式匹配!因此要求先查看U命令的輸出結果。 |
|
ld |
ld (Load Symbols) ld [ModuleName] 加載調試信息。在對付lazy load的dll時比較有用。 |
|
ln |
ln (List Nearest Symbols) ln Address The ln command displays the symbols at or near the given address. |
|
ls, lsa |
ls, lsa (List Source Lines) ls [.] [first] [, count] lsa [.] address [, first [, count]] |
|
.context |
.context (Set User-Mode Address Context) .context [PageDirectoryBase] PDB地址來自.process命令 kd> !process 0 0 PROCESS fe3c0d60 SessionId: 0 Cid: 0208 Peb: 7ffdf000 ParentCid: 00d4 DirBase: 0011f000 ObjectTable: fe3d0f48 TableSize: 30. Image: regsvc.exe |
|
.process |
.process (Set Process Context) The .process command specifies which process is used for the process context. Syntax .process [/i] [/p [/r] ] [/P] [Process] |
|
.thread |
.thread (Set Register Context) The .thread command specifies which thread will be used for the register context. Syntax .thread [/p [/r] ] [/P] [/w] [Thread] |
|
.time |
.time (Display System Time) 0:000> .time Debug session time: Mon Apr 07 19:10:50 2003 System Uptime: 4 days 4:53:56.461 OS已經運行了多久 Process Uptime: 0 days 0:00:08.750 進程已經運行了多久 Kernel time: 0 days 0:00:00.015 User time: 0 days 0:00:00.015 |
|
.ttime |
The .ttime command displays the running times for a thread. 0:000> .ttime Created: Sat Jun 28 17:58:42 2003 Kernel: 0 days 0:00:00.131 User: 0 days 0:00:02.109 |
|
.writemem |
.writemem FileName Range |
|
![exts.]peb |
The !peb extension displays a formatted view of the information in the process environment block (PEB). Syntax !peb [PEB-Address] |
|
![exts.]teb |
The !teb extension displays a formatted view of the information in the thread environment block (TEB). Syntax !teb [TEB-Address] |
|
![exts.]tls |
The !tls extension displays a thread local storage (TLS) slot. Syntax !tls Slot [TEB] Parameters Slot Specifies the TLS slot. This can be any value between 0 and 1088 (decimal). If Slot is -1, all slots are displayed. TEB Specifies the thread environment block (TEB). If this is 0 or omitted, the current thread is used. |
|
![ntsdexts.]locks |
!locks [-v][-o] - Dump all Critical Sections in process |
2.2. 常用命令
得到dump文件:
Adplus -hang -pn w3wp.exe -quiet (hang) [-FullOnFirst]
adplus -crash -pn w3wp.exe (crash)
加載 sos 擴展功能dll:
.load sos.dll
.loadby sos mscorwks
自動分析
!analyze –v
!analyze -hang。這個擴展將會執行一個線程棧分析以確定是不是有哪些線程正在阻塞其他線程。
查看版本:
!eeversion
查看異常:
!dumpallexceptions
運行 help 命令:
!help
!help [command name] //查找某個命令更多詳細的內容, 如: !help eeversion
顯示系統與時間有關的信息:
.time
dump文件時cpu的使用情況。同時可以得到其他的有用的信息(例如:等待請求隊列的數量,已完成的線程和時間):
!threadpool
列出當前正在運行的線程和cpu使用情況
!runaway //比如查看哪個線程占用 CPU 時間過多
列表顯示出應用程序所有正在運行的線程,當前應用程序域中后台正在運行的程序,等等線程相關內容
!threads
切換到特定的線程上查看相關內容
~[thread id]s //例如: ~2s
列出當前線程中的調用棧信息
!clrstack //如果想查看額外的信息,添加 “-p”選項, 如: !clrstack –p
!clrstack -a
顯示指定地址對象的內容:
!dumpobj 0xf32fcc //(!do 為簡寫)
繼續查看對象的值
!dumpobj -v 0xf32fcc
!dumpvc 7910c878 01573774 //mt value
查看當前特定線程的堆棧中所有托管對象
!dumpstackobjects (或 簡稱!dso ) //next: !dumpobj 0x1d298ad8
得到當前線程對象中關於數組對象的詳細信息
!dumparray [address] (簡稱!da) //!do [address]僅得到簡單信息
!da –details [address] //詳細信息
得到對象的整個大小
!objsize 071bef70
!objsize poi(0x61b47d4+0xc) //Address + Offset
.foreach (obj {!dumpheap -mt 0x0c2eaeb4 -short}){!objsize ${obj}} //0x0c2eaeb4: mt
.foreach(myobj {!dumpheap -short -min 85000}) {!objsize myobj} //所有所有對象中大於85K內容
dump出所有的托管堆上的對象
!dumpheap –stat //使用 –stat 參數來得到托管堆上的摘要信息
參數–mt (即:MethodTable):
!dumpheap -mt 793308ec //next: 進一步查看對象,使用 !dumpobj [object address]即可
參數–mt:
!dumpheap –type System //出許多包含 System 名稱的對象
參數是 –min \ -max ,該參數接受一個最小\最大的對象字節數:
!dumpheap –stat –min 85000 //查看大於85000bytes字節的對象
!dumpheap -min 85000
!dumpheap -mt 790fd8c4 -min 20000 -max 25000
!dumpheap -type System.String -min 150 -max 200 //檢查大小在 150 至 200 之間的所有字符串
!dumpheap -mt 790fd8c4 -strings //只輸出字符串
參數-short:
!dumpheap -type System.String -min 6500 –short //僅僅查詢出對象的地址信息
.foreach語句:
.foreach (myAddr {!dumpheap -type System.String -min 6500 -short}){!dumpobj myAddr;.echo **************************} // .echo 命令打印分割符
.shell命令:
.shell -i - -ci "!iisinfo.clientconns" FIND /c "Request active"
.shell -i - -ci "!iisinfo.clientconns" FIND /c "<table"
!dumpobj 04aa1a90 // 查看對象的詳細信息
!dumpclass 0x6c632e8 // 查看類型的詳細信息
!dumpmt -md 0x09750a8 // 查看方法表的詳細信息
!dumpmd 0x00975070 // 查看方法表項的方法描述的詳細信息
u 0x79b7c4eb // 反匯編指定地址的指令
[http://www.cnblogs.com/flier/archive/2004/07/08/22361.html]
查看進程程序集加載情況:
!dumpdomain
將進程程序集導出
!SaveModule 00992c5c z:\temp\a.dll
顯示模塊信息:
!dumpmodule [-mt] 1c5a1098 //1c5a1098: module address
查看native內存內容:
MetaData start address: 1d3b09e4 (4184 bytes)
dc 1d3b09e4 1d3b09e4+0n4184
du 3cd30038 3cd30038 +1000
[異常]
查看托管線程
!threads
查看所有的Exception:
!dumpheap –type Exception
命令將打印出當前堆棧上正在被拋出的exception
!pe/!PrintException
打印出相應命令的詳細信息及堆棧:
!pe address
查看某個具體的異常的詳細信息
!do [address]
!do –nofields [address] //string類型簡單輸出格式
查看對象的信息:
!gcroot [address]
打印出所有的同一個類型的Exception的信息
.foreach(myVariable {!dumpheap -type System.ArgumentNullException -short}){!pe myVariable;.echo **}
//OutOfMemoryException? StackOverflowException? System.OutOfMemoryException?
列出了GC 堆的大小 和G0,G1,G2 ,LOH的開始地址:
!EEHeap [-gc] [-loader]
!eeheap
!eeheap –gc
!eeheap -loader
查看內存信息
!name2ee * WindbgDemo.Program
查看方法描述
!dumpmd 00993034
查看方法表信息
!dumpmt -md 0099304c
查看il
!dumpil 00993034
Dump文件
C:\Program Files\Debugging Tools for Windows (x86) adplus.vbs -hang -o C:\dump -p 6876
參數說明:
?-hang: 表示附加到目標進程,抓取 dump 鏡像,然后解除。對應的參數是 -crash 崩潰模式,該參數會終止目標進程。
?-o: 指定 Dump 文件保存路徑。
?-p: 指定目標進程 PID。
Jitted代碼:
- sxe ld:mscorjit.dll
- 2. .loadby sos mscorwks
- !name2ee test.exe System.Program.Main
- ba w4 975070+0x04 "bp poi(975070+0x04);g"
- !clrstack
Ngened代碼:
http://blog.joycode.com/gangp/archive/2004/04/28/20417.joy
1、!analyze -v :用於分析掛掉線程的詳細情形,錯誤原因。
2、!locks :列出全部資源使用情況。
3、!locks -v 0x???????? :特定地址的死鎖分析。
4、!thread 0x????????:特定線程詳情。
5、.thread 0x????????:轉到某個線程堆棧。
2.3. ~
查看系統當前線程,使用~*s命令切換線程,如需要切換到8號線程,可以使用命令:~8s
0:004> ~
0 Id: dd0.7c0 Suspend: 1 Teb: 7ffdf000 Unfrozen
1 Id: dd0.1230 Suspend: 1 Teb: 7ffde000 Unfrozen
2 Id: dd0.bc4 Suspend: 1 Teb: 7ffdd000 Unfrozen
3 Id: dd0.1424 Suspend: 1 Teb: 7ffdc000 Unfrozen
. 4 Id: dd0.ba8 Suspend: 1 Teb: 7ffdb000 Unfrozen
2.4. .load sos
加載微軟提供的調試擴展工具,可以更方便的調試托管代碼。只有加載SOS之后,才能使用下面的這些命令。
0:004> .load sos
2.5. !clrstack
查看當前線程的調用棧,如果想查看所有進程的調用棧情況, 使用~*e !clrstack
0:000> !clrstack
OS Thread Id: 0x7c0 (0)
ESP EIP
002aee00 775564f4 [NDirectMethodFrameStandalone: 002aee00] System.Windows.Forms.SafeNativeMethods.MessageBox(System.Runtime.InteropServices.HandleRef, System.String, System.String, Int32)
002aee1c 66fffd28 System.Windows.Forms.MessageBox.ShowCore(System.Windows.Forms.IWin32Window, System.String, System.String, System.Windows.Forms.MessageBoxButtons, System.Windows.Forms.MessageBoxIcon, System.Windows.Forms.MessageBoxDefaultButton, System.Windows.Forms.MessageBoxOptions, Boolean)
002aeebc 66fff93e System.Windows.Forms.MessageBox.Show(System.String)
002aeec4 006603ab TestCode4AQTime.Form1.button1_Click(System.Object, System.EventArgs)
002aeee0 669d4170 System.Windows.Forms.Control.OnClick(System.EventArgs)
002af04c 66a023b0 System.Windows.Forms.Button.WndProc(System.Windows.Forms.Message ByRef)
002af058 66a084a0
002af218 007c09e4 [NDirectMethodFrameStandalone: 002af218] System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef)
002af228 66a18aee System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)
002af2c4 66a18757 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
002af318 66a185a1 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
002af348 669d5911 System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
002af35c 006600ae TestCode4AQTime.Program.Main()
2.6. !do(DumpObj)
查看class對象內容。!do [對象的內存地址]
0:000> !do 01e80d5c
Name: System.String
MethodTable: 68eb88c0
EEClass: 68c7a498
Size: 102(0x66) bytes
(C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: system.serviceModel.activation/diagnostics
Fields:
MT Field Offset Type VT Attr Value Name
68ebab0c 4000096 4 System.Int32 1 instance 43 m_arrayLength
68ebab0c 4000097 8 System.Int32 1 instance 42 m_stringLength
68eb95a0 4000098 c System.Char 1 instance 73 m_firstChar
68eb88c0 4000099 10 System.String 0 shared static Empty
>> Domain:Value 003a5698:01e61198 <<
68eb94f0 400009a 14 System.Char[] 0 shared static WhitespaceChars
>> Domain:Value 003a5698:01e6174c <<
!dumpvc(dv) 命令查看Value類型對象,對應c#的struct對象
2.7. !dso(DumpStackObjects)
查看棧上對象。
0:000> !dso
OS Thread Id: 0x7c0 (0)
ESP/REG Object Name
002aede0 01e61198 System.String
002aede4 01e995c4 System.String Finished
002aedf8 01e9760c System.Windows.Forms.MouseEventArgs
002aee4c 01e995c4 System.String Finished
002aee90 01e9760c System.Windows.Forms.MouseEventArgs
002aee94 01e995c4 System.String Finished
002aee98 01e87bfc System.Windows.Forms.Button
002aeeb8 01e61198 System.String
002aeebc 01e88af0 System.EventHandler
002aeec4 01e69a54 TestCode4AQTime.Form1
002aeed0 01e87bfc System.Windows.Forms.Button
002aeedc 01e9760c System.Windows.Forms.MouseEventArgs
002aeee0 01e87d98 System.ComponentModel.EventHandlerList
2.8. !dumpheap
查看托管堆內存對象信息。
!dumpheap –stat 只輸出統計信息(常用)
!dumpheap –type <partial type name> 只輸出類型名和給出(部分)類型名稱匹配的對象
0:000> !dumpheap -stat
total 4843 objects
Statistics:
MT Count TotalSize Class Name
68ebaa5c 36 3776 System.Int32[]
68728c6c 95 5320 System.Configuration.FactoryRecord
68ebb010 32 10224 System.Collections.Hashtable+bucket[]
68eb94f0 41 10544 System.Char[]
68eba468 666 15984 System.Version
68ebb330 17 25528 System.Byte[]
68e94eec 231 41168 System.Object[]
68eb88c0 1102 89616 System.String
Total 4843 objects
2.9. !objsize
查看對象實際占用內存大小
0:000> !objsize 01e80d5c
sizeof(01e80d5c) = 104 ( 0x68) bytes (System.String)
2.10. !gcroot
查找對象引用關系
0:000> !gcroot 01e80d5c
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSTHread 7c0
Scan Thread 2 OSTHread bc4
DOMAIN(003A5698):HANDLE(Pinned):2f13e4:Root:02e65dd8(System.Object[])->
01e6d8cc(System.Configuration.ClientConfigurationSystem)->
01e6f22c(System.Configuration.RuntimeConfigurationRecord)->
01e7481c(System.Collections.Hashtable)->
01e7e760(System.Collections.Hashtable+bucket[])
2.11. !da(DumpArray)
查看數組對象
0:000> !da 02e65dd8
Name: System.Object[]
MethodTable: 68e94eec
EEClass: 68c7a8a0
Size: 4096(0x1000) bytes
Array: Rank 1, Number of elements 1020, Type CLASS
Element Methodtable: 68eb84dc
[0] null
[1] null
[2] 01e88f00
[3] null
[4] null
[5] 01e88ef4
[6] null
[7] null
[8] null
2.12. !threads
列出當前進程中的托管線程,可以查看托管線程和系統線程的對應關系。
0:004> !threads
ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
0 1 e6c 0026aeb8 6020 Enabled 018bd010:018bdfe8 00265698 0 STA
2 2 c08 002790f0 b220 Enabled 00000000:00000000 00265698 0 MTA (Finalizer)
2.13. !eeheap
通過!eeheap,可以查看CLR堆的使用情況。
!eeheap –gc:只查看GC堆的輸出結果。
!eeheap –loader:查看和AppDomains關聯的各種私有堆的輸出結果。
0:004> !eeheap -loader
Loader Heap:
--------------------------------------
System Domain: 726ee1f8
LowFrequencyHeap: Size: 0x0(0)bytes.
HighFrequencyHeap: 00232000(8000:1000) Size: 0x1000(4096)bytes.
StubHeap: 0023a000(2000:2000) 00c50000(10000:3000) Size: 0x5000(20480)bytes.
Virtual Call Stub Heap:
IndcellHeap: Size: 0x0(0)bytes.
LookupHeap: Size: 0x0(0)bytes.
ResolveHeap: Size: 0x0(0)bytes.
DispatchHeap: Size: 0x0(0)bytes.
CacheEntryHeap: Size: 0x0(0)bytes.
Total size: 0x6000(24576)bytes
--------------------------------------
Shared Domain: 726edb48
LowFrequencyHeap: 00430000(2000:1000) Size: 0x1000(4096)bytes.
HighFrequencyHeap: 00432000(8000:1000) Size: 0x1000(4096)bytes.
StubHeap: 0043a000(2000:1000) Size: 0x1000(4096)bytes.
Virtual Call Stub Heap:
IndcellHeap: 00480000(2000:1000) Size: 0x1000(4096)bytes.
LookupHeap: 00485000(2000:1000) Size: 0x1000(4096)bytes.
ResolveHeap: 0048b000(5000:1000) Size: 0x1000(4096)bytes.
DispatchHeap: 00487000(4000:1000) Size: 0x1000(4096)bytes.
CacheEntryHeap: 00482000(3000:1000) Size: 0x1000(4096)bytes.
Total size: 0x7000(28672)bytes
--------------------------------------
Domain 1: 265698
LowFrequencyHeap: 00410000(2000:2000) 006c0000(10000:1000) Size: 0x3000(12288)bytes.
HighFrequencyHeap: 00412000(8000:5000) Size: 0x5000(20480)bytes.
StubHeap: 0041a000(2000:1000) Size: 0x1000(4096)bytes.
Virtual Call Stub Heap:
IndcellHeap: 00420000(2000:1000) Size: 0x1000(4096)bytes.
LookupHeap: 00426000(1000:1000) Size: 0x1000(4096)bytes.
ResolveHeap: 0042a000(6000:2000) Size: 0x2000(8192)bytes.
DispatchHeap: 00427000(3000:1000) Size: 0x1000(4096)bytes.
CacheEntryHeap: 00422000(4000:1000) Size: 0x1000(4096)bytes.
Total size: 0xe000(57344)bytes
--------------------------------------
Jit code heap:
LoaderCodeHeap: 004e0000(10000:1000) Size: 0x1000(4096)bytes.
Total size: 0x1000(4096)bytes
--------------------------------------
Module Thunk heaps:
Module 72741000: Size: 0x0(0)bytes.
Module 00432358: Size: 0x0(0)bytes.
Module 00432010: Size: 0x0(0)bytes.
Module 00412c5c: Size: 0x0(0)bytes.
Module 66701000: Size: 0x0(0)bytes.
Module 672e1000: Size: 0x0(0)bytes.
Module 67f61000: Size: 0x0(0)bytes.
Module 65ab1000: Size: 0x0(0)bytes.
Module 65571000: Size: 0x0(0)bytes.
Total size: 0x0(0)bytes
--------------------------------------
Module Lookup Table heaps:
Module 72741000: Size: 0x0(0)bytes.
Module 00432358: Size: 0x0(0)bytes.
Module 00432010: Size: 0x0(0)bytes.
Module 00412c5c: Size: 0x0(0)bytes.
Module 66701000: Size: 0x0(0)bytes.
Module 672e1000: Size: 0x0(0)bytes.
Module 67f61000: Size: 0x0(0)bytes.
Module 65ab1000: Size: 0x0(0)bytes.
Module 65571000: Size: 0x0(0)bytes.
Total size: 0x0(0)bytes
--------------------------------------
Total LoaderHeap size: 0x1c000(114688)bytes
=======================================
0:004> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x01881018
generation 1 starts at 0x0188100c
generation 2 starts at 0x01881000
ephemeral segment allocation context: none
segment begin allocated size
01880000 01881000 018bdff4 0x0003cff4(249844)
Large object heap starts at 0x02881000
segment begin allocated size
02880000 02881000 02886de8 0x00005de8(24040)
Total Size 0x42ddc(273884)
------------------------------
GC Heap Size 0x42ddc(273884)
2.14. 轉儲進程
直接使用微軟提供的aplus.vbs腳本轉儲w3wp.exe進程
Cscript adplus.vbs –hang –pn w3wp.exe –o <Dump存儲目錄> -quiet –do
使用Windbg命令轉儲進程
.dump /f <Dump存儲文件>
第三章 常見問題
3.1. OutOfMemory
解決思路:
使用!dumpheap –stat命令檢查托管堆對象。
使用gcroot查找數量/大小不正常對象的引用鏈,以明確對象沒被GC回收的原因
3.2. 系統緩慢&HighCPU&單點效率異常
解決思路:
使用!clrstack命令,多次抓取系統調用棧。
比較調用棧停留位置,找到可疑處。
通過!do&!dso查看棧變量,判斷代碼調用棧停留位置效率低下原因。
第四章 應用示例
示例1: 緩存對象
1. 檢查緩存大小
!dumpheap –stat –type System.Web.Caching.Cache //得到了 System.Web.Caching.Cache 對象的方法表
!dumpheap –mt 1230494c //得到1230494c方法表中所有對象
!objsize 03392d20 //得到當前地址對應對象的大小
2. 什么內容被緩存了?
!dumpheap –stat –type System.Web.Caching //查看 CacheEntrys 對象
!dumpheap -mt 12306320 //查看CacheEntrys的方法表MT
!do 076b42dc //檢查對象的所有內容, 之后
示例2: 掛起
檢查堆棧信息
檢查本地的堆棧信息:
~* kb 2000
檢查 dotnet 堆棧信息:
~* e!clrstack // Do you see any patterns or recognize any of the callstacks that suggests a thread is waiting for a synchronization mechanism?
看看有多少調用堆棧里有Monitor.Enter:
.shell -ci "~* e !clrstack" FIND /C Monitor.Enter
跟蹤診斷掛起現象
檢查等待鎖的線程ID列表:
!syncblk //(提示:MonitorHeld = 1 代表擁有者,2為等待者)
查看一個等待線程的狀態:
~5s (切換到線程 5,用真實的線程ID替換5即可)
kb 2000 (檢查本地堆棧信息)
!clrstack (查看dotnet 堆棧信息)
!clrstack –p (查看dotnet 堆棧信息,包括參數內存地址)
!clrstack –a
示例3: 查看緩存占用情況
查看Cache占用內存情況:
!name2ee System.Web.dll System.Web.Caching.Cache
0:000> !name2ee System.Web.dll System.Web.Caching.Cache
Module: 65f21000 (System.Web.dll)
Token: 0x020000fa
MethodTable: 66148d24
EEClass: 65f86838
Name: System.Web.Caching.Cache
!dumpheap –mt [MethodTable] //查看托管堆中對象類型
!objsize 06952248 //查看對象大小
示例4: 內存調試
首先看看GC heap的大小,和dump 文件比較一下。
這個 !eeheap 命令列出了GC 堆的大小 和G0,G1,G2 ,LOH的開始地址。
0:001> !eeheap –gc
generation 0 starts at 0x0110be64
generation 1 starts at 0x01109cd8
generation 2 starts at 0x01021028
segment begin allocated size
01020000 01021028 0110de70 000ece48(970312)
Total Size 0xece48(970312)
------------------------------
large block 0x11e1fc04(300022788)
large_np_objects start at 17b90008
large_p_objects start at 02020008
------------------------------
GC Heap Size 0x11f0ca4c(300993100)
在這里GC 堆是300M左右,dump文件是358M。
使用 !dumpheap –stat 命令來查看占用了空間的托管對象。
0:001> !dumpheap -stat
Bad MethodTable for Obj at 0110d2a4
Last good object: 0110d280
total 14459 objects
Statistics:
MT Count TotalSize Class Name
3c6185c 1 12 System.Web.UI.ValidatorCollection
3c2e110 1 12 System.Web.Configuration.MachineKeyConfigHandler
3c29778 1 12 System.Web.Configuration.HttpCapabilitiesSectionHandler
3c23240 1 12 System.Web.SafeStringResource
… …
D12f28 1133 46052 System.Object[]
153cb0 88 76216 Free
321b278 85 178972 System.Byte[]
d141b0 6612 416720 System.String
Total 14459 objects
使用!gcroot 16220018從LOH上得到更多對象的信息:
0:001> !gcroot 16220018
Scan Thread 1 (4e8)
Scan Thread 5 (bb0)
Scan Thread 6 (d0)
Scan Thread 10 (43c)
Scan Thread 11 (308)
Scan Thread 12 (6e4)
Scan HandleTable 14e340
Scan HandleTable 150e40
Scan HandleTable 1a6fa8
HANDLE(Strong):37411d8:Root:020784d8(System.Object[])-
>0108b504(System.Web.HttpRuntime)->0108b9d0(System.Web.Caching.CacheSingle)-
>0108ca68(System.Web.Caching.CacheUsage)->0108ca78(System.Object[])-
>0108cb3c(System.Web.Caching.UsageBucket)-
>010f95fc(System.Web.Caching.UsageEntry[])-
>01109be8 (System.Web.Caching.CacheEntry)->00000000()
要找出System.Web.Caching.Cache的地址,請使用 !name2ee命令,這個命令接受2個參數 程序集的名字和全類名:
0:001> !name2ee System.Web.dll System.Web.Caching.Cache
--------------------------------------
MethodTable: 03887998
EEClass: 03768814
Name: System.Web.Caching.Cache
--------------------------------------
EEClass 是一個用來表示.net 類的內部結構。
取得托管堆中的某個對象的類型,使用 !dumpheap –mt MethodTable地址 的方式來獲得:
0:001> !dumpheap -mt 03887998
Address MT Size
0108b8ac 03887998 12
Bad MethodTable for Obj at 0110d2a4
Last good object: 0110d280
total 1 objects
Statistics:
MT Count TotalSize Class Name
3887998 1 12 System.Web.Caching.Cache
Total 1 objects
large objects
Address MT Size
total 0 large objects
查看 System.Web.Caching.Cache 的大小,使用 !objsize 0108b8ac:
0:001> !objsize 0108b8ac
sizeof(0108b8ac) = 300126128 (0x11e38fb0) bytes (System.Web.Caching.Cache)
修正代碼,把緩存移除。重新裝載 dump文件,加載模塊,使用 !eeheap –gc 來看看托管堆的大小:
0:000> !eeheap -gc
generation 0 starts at 0x012cc0e4
generation 1 starts at 0x012afde8
generation 2 starts at 0x011c1028
segment begin allocated size
011c0000 011c1028 012d6000 00114fd8(1134552)
Total Size 0x114fd8(1134552)
------------------------------
large block 0x8060(32864)
large_np_objects start at 00000000
large_p_objects start at 021c0008
------------------------------
GC Heap Size 0x11d038(1167416)
dump 顯示 GC 堆的大小是1M,不是222M,這表示除了1M其它的都被收集了。
示例5: 內存泄露跟蹤
I.查看內存使用概要:
!address -summary
0:000> !address -summary
-------------------- Usage SUMMARY --------------------------
TotSize ( KB) Pct(Tots) Pct(Busy) Usage
373b7000 ( 904924) : 21.58% 85.85% : RegionUsageIsVAD
bfa89000 ( 3140132) : 74.87% 00.00% : RegionUsageFree
76e6000 ( 121752) : 02.90% 11.55% : RegionUsageImage
67c000 ( 6640) : 00.16% 00.63% : RegionUsageStack
0 ( 0) : 00.00% 00.00% : RegionUsageTeb
144a000 ( 20776) : 00.50% 01.97% : RegionUsageHeap
0 ( 0) : 00.00% 00.00% : RegionUsagePageHeap
1000 ( 4) : 00.00% 00.00% : RegionUsagePeb
1000 ( 4) : 00.00% 00.00% : RegionUsageProcessParametrs
2000 ( 8) : 00.00% 00.00% : RegionUsageEnvironmentBlock
Tot: ffff0000 (4194240 KB) Busy: 40567000 (1054108 KB)
-------------------- Type SUMMARY --------------------------
TotSize ( KB) Pct(Tots) Usage
bfa89000 ( 3140132) : 74.87% :
834e000 ( 134456) : 03.21% : MEM_IMAGE [總共內存占用百分比]
95a000 ( 9576) : 00.23% : MEM_MAPPED
378bf000 ( 910076) : 21.70% : MEM_PRIVATE
-------------------- State SUMMARY --------------------------
TotSize ( KB) Pct(Tots) Usage
34bea000 ( 864168) : 20.60% : MEM_COMMIT
bfa89000 ( 3140132) : 74.87% : MEM_FREE
b97d000 ( 189940) : 04.53% : MEM_RESERVE
Largest free region: Base 80010000 - Size 7fefa000 (2096104 KB)
這里有非常多的信息,但所有的這些都不是這么明顯的。相信我,讓我們花一些時間在這里。在任何一個案例中,我用這個來幫助我指出我需要查看哪些地方,所以我不介意它要花費多少,即使就是一個概述的結果。
一些要注意的地方:
上面一屏顯示了按照類型不同而分類顯示的由進程使用的內存。第一部分是按照區域類型來划分的,它按照什么樣子的分配類型告訴你信息。最常遇到的一個類型是VAD = Virtual Alloc, Image = dlls 和 exes,Heap = heaps the process owns,從WinDbg的幫助中可以得到更多的信息。接着下面是按IMAGE, MAPPED 或 PRIVATE 的類型來列出,最后一部分是按已提交(also committed,就是指實際已經分配的)或保留(reserved)的方式來列出它們。 RegionUsageheap,代表的是NT heaps;MEM_COMMIT和MEM_RESERVE加起來,是virtual memory。
Tot: ffff0000 (4 194 240 kb) :的意思是我總共有4GB的虛擬內存地址空間提供給這個應用程序。32位系統上,你可以尋地4GB的空間,典型的是2GB的用戶模式的內存空間,所以一般你會看到2GB而不是這里的4GB,在64位上,運行一個32位的進程會得到完全的4GB的空間,所以我這里看到的是4GB。
Busy: 40567000 (1 054 108 kb) 是我們已經使用的(已經分配的)。
MEM_PRIVATE是一個私有的內存,它不和其他進程共享內存,不是映射到文件的內存。不要把這個和性能計數器中的Private Bytes混淆。這里的MEM_PRIVATE 是保留+已提交(即已分配的)(reserved + committed)的字節數,另外那個Private Bytes 是申請/已提交(allocated/committed)的字節數。
MEM_PRIVATE 是已經提交(已經分配)的內存(不一定是 private的),這個可能是最接近你得到的Private Bytes的。
MEM_RESERVE 是已經保留的,但沒有實際分配的,未提交的內存。所有已經分配的內存也是定義為保留的,所以如果你查看所有保留的內存(最接近你得到的virtual bytes),你必須加上MEM_COMMIT和 MEM_RESERVE,它是顯示在Busy 中的那個數字。你自己把數字加上后比對一下看看。
Q:哪個值最能代表如下兩個指標?
·Private Bytes A: MEM_COMMIT
·Virtual Bytes A: Busy
Q:大部分的內存都去哪里了?(哪個區域)
A:在這里,大約904MB是為VAD保留的,VAD是dotnet對象存放的地方,因為GC堆是virtual allocs 分配的。
Q:Busy,Pct(Busy),Pct(Tots)是什么意思?
A:Pct(Tots) 顯示的是整個虛擬地址空間中分配給不同區域類型的百分比。Pct(Busy)顯示的是保留的內存中分配給不同區域的百分比。Pct(busy) 很顯然是我最關心的一個。
Q:MEM_IMAGE 是什么意思?
A:從幫助文件中我們知道:這個是表示從一個可執行的映射文件的一部分映射到的內存。換句話說 就是dll 或一個exe 文件的內存映射。
Q:哪個區域的.net 內存是適宜的,為什么?
A:在RegionUsageIsVAD,理由如上。
從性能計數器中我們看到#Bytes in all Heaps 跟隨着Private bytes的增長而增長,那說明了內存的增加幾乎都是.net 的使用而增加的,進而我們轉化為為什么.net 的GC堆(heap)始終在增長。
|
II.運行 !eeheap –gc 來查看.net GC 堆的大小
0:000> !eeheap -gc
Number of GC Heaps: 2
------------------------------
Heap 0 (001aa148)
generation 0 starts at 0x32f0639c
generation 1 starts at 0x32ae3754
generation 2 starts at 0x02eb0038
ephemeral segment allocation context: none
segment begin allocated size
001bfe10 7a733370 7a754b98 0x00021828(137256)
001b0f10 790d8620 790f7d8c 0x0001f76c(128876)
…..
Large object heap starts at 0x0aeb0038
segment begin allocated size
0aeb0000 0aeb0038 0aec0b28 0x00010af0(68336)
Heap Size 0x15fd1310(368907024)
------------------------------
Heap 1 (001ab108)
generation 0 starts at 0x36e665bc
generation 1 starts at 0x36a28044
generation 2 starts at 0x06eb0038
ephemeral segment allocation context: none
segment begin allocated size
06eb0000 06eb0038 0aea58d4 0x03ff589c(67066012)
……
Large object heap starts at 0x0ceb0038
segment begin allocated size
0ceb0000 0ceb0038 0ceb0048 0x00000010(16)
Heap Size 0x15ab1570(363533680)
------------------------------
GC Heap Size 0x2ba82880(732440704)
Q:總共有多少個Heap,為什么?
A:這里有兩個堆,因為我們運行在多核進程模型中。
Q:有多少內存被保存在了.net GC 堆中?拿#Bytes in all Heaps比較一下。
A:GC的堆大小是:GC Heap Size 0x2ba82880(732 440 704),它和性能計數器中的bytes in all heaps很接近。
Q:large object heap 上有多少內存?提示:把large object heap段上的合計加起來,和性能計數器中的Large Object Heap Size 比較一下。
A:它是非常小的,所以LOH看起來不是問題所在,大小是68 336 + 16 bytes
|
III. 運行 !dumpheap –stat 來輸出所有的以統計式樣表示的.net 對象
Q:查看 5 到10個使用了大部分內存的對象,思考一下是什么泄露了?
A:
66424cf4 37 57276 System.Web.Caching.ExpiresEntry[]
663b0cdc 4001 192048 System.Web.SessionState.InProcSessionState
7912d8f8 3784 255028 System.Object[]
7912d9bc 820 273384 System.Collections.Hashtable+bucket[]
6639e4c0 4037 290664 System.Web.Caching.CacheEntry
0fe11cf4 36000 576000 Link
790fdc5c 36161 723220 System.Text.StringBuilder
001a90c0 1105 7413924 Free
790fd8c4 51311 721773112 System.String
Total 163943 objects
大部分的內存是被strings用掉了,這個不太正常,雖然strings 在應用中是最常見的,但是大約721MB的顯然有點怪異,並且有3600個Links(無論它們是什么),看起來有點奇怪。特別是因為有差不多數量的stringbuilds 出現在dump中。
Q:“size”那個行顯示了什么?例如,“size”這行包含了什么?
A:如果我們用命令!do 把Link 對象輸出來,我們看到有一個指針指向stringbuilder(url)和一個指針指向string(name),link對象的大小是16B,這個大小僅僅包含了指針的大小和其他一些開銷(methos table 等)。
如果你運行 !objsize ,你會看見大小是高達20144 B ,這個大小是包含成員變量的,比如Link對象的大小和它引用的所有對象。
你看到了什么通過!dumpheap 輸出的16B的每一個link。它不包含成員變量的大小是由一些不同原因的:
1)它將要花費很長的時間去計算大小。
2) 一些對象(假如是A和B)可能都指向C對象,如果你使用 !objsize 計算A 和B的大小,他們都會包含C的大小,所以size這個列的值會變得很復雜難以計算。
3) 在這個例子中Link的大小size看起來似乎是正常的。因為一個link對象包含一個url和一個name。但是如果一個web 控件可能會包含一個成員變量 _parent ,如果你運運行 !objsize ,這樣就會包含父對象(page)那就顯然是不合適的。
0:000> !do 371d44cc
Name: Link
MethodTable: 0fe11cf4
EEClass: 0fde5824
Size: 16(0x10) bytes
(C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\
Temporary ASP.NET Files\buggybits\b27906cc\f5f91899\App_Code.wbwztx_4.dll)
Fields:
MT Field Offset Type VT Attr Value Name
790fdc5c 4000006 4 ...ext.StringBuilder 0 instance 371d44dc url
790fd8c4 4000007 8 System.String 0 instance 02f13cd8 name
0:000> !objsize 371d44cc
sizeof(371d44cc) = 20144 ( 0x4eb0) bytes (Link)
通常,我不推薦立刻查看在你的這個非常簡單的dump文件中,在該命令輸出的底部的strings,因為:
· strings 這一行的“size”是實際的字符串string的有內容的真實大小。如果你和DataSet比較,這個“size”只是包含了行和列的指針,並沒有包含行和列的內存。所以DataSet這個對象的大小幾乎總是非常的小的。
· string 字符串在大部分的對象中幾乎是葉子節點,例如,dataset包含字符串,aspx頁面包含字符串,session 變量也包含字符串。所以,在一個應用中幾乎都是字符串。
然而在這個例子中,字符串有這么多,占有了那么多的內存。如果我們不查到其他一些阻止了我們的東西,那我們可能就要沿着string 這條路走下去了。
|
IV. 把各種不同大小的string 都輸出來
得到string的 MT(method table),!dumpheap –stat 的輸出結果的第一列。
!dumpheap -mt <string MT> -min 85000 -stat
!dumpheap -mt <string MT> -min 10000 -stat
!dumpheap -mt <string MT> -min 20000 -stat
!dumpheap -mt <string MT> -min 30000 -stat
!dumpheap -mt <string MT> -min 25000 -stat
Q:大部分的string’在一個什么樣的范圍內?
A:在 20000 和 25000 字節之間。
V. 把那個范圍內的string 輸出來。
!dumpheap -mt <string MT> -min 20000 -max 25000
在這里,它們中的大部分是一模一樣的大小的,這是一個指引我們向下前進的線索。
0:000> !dumpheap -mt 790fd8c4 -min 20000 -max 25000
------------------------------
Heap 0
Address MT Size
02f1412c 790fd8c4 20020
02f2d96c 790fd8c4 20020
02f327c4 790fd8c4 20020
02f3761c 790fd8c4 20020
02f3c474 790fd8c4 20020
02f412cc 790fd8c4 20020
02f46124 790fd8c4 20020
02f4af7c 790fd8c4 20020
02f4fdd4 790fd8c4 20020
02f54c2c 790fd8c4 20020
...
VI.把它們中的一些輸出來看看里面是什么
!do <address of string> ,地址是 !dumpheap -mt 輸出的第一列。
0:000> !do 02f327c4
...
String: http://www.sula.cn
...
Q:這些string里面包含的是什么?
A:好像link.aspx 頁面顯示了link對象。
VII. 揀幾個,看看它們被根化(rooted)到哪里(即為什么它們不會被回收)。注意你可能需要嘗試不同的幾個才行.
!gcroot <address of string>
0:000> !gcroot 02f327c4
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 16 OSTHread 1948
Scan Thread 20 OSTHread 1b94
Scan Thread 21 OSTHread 1924
Scan Thread 22 OSTHread 188c
Scan Thread 14 OSTHread 1120
Scan Thread 24 OSTHread 13f8
Finalizer queue:Root:02f327a0(Link)->
02f327b0(System.Text.StringBuilder)->
02f327c4(System.String)
Q:它們被根化到哪里?為什么?
A:這個string是一個string builder 類型的成員變量,它表現的是一個link的成員變量(url),link 對象被根化在終結器隊列中,那就是說他正在等待被終結。
檢查終結器隊列(finalizer queue)和終結線程(finalizer thread)
1)查看終結器隊列
!finalizequeue
0:000> !finalizequeue
SyncBlocks to be cleaned up: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
------------------------------
Heap 0
generation 0 has 221 finalizable objects (0f44a764->0f44aad8)
generation 1 has 0 finalizable objects (0f44a764->0f44a764)
generation 2 has 45 finalizable objects (0f44a6b0->0f44a764)
Ready for finalization 18009 objects (0f44aad8->0f45c43c)
------------------------------
Heap 1
generation 0 has 338 finalizable objects (0f45d840->0f45dd88)
generation 1 has 4 finalizable objects (0f45d830->0f45d840)
generation 2 has 36 finalizable objects (0f45d7a0->0f45d830)
Ready for finalization 17707 objects (0f45dd88->0f46f234)
Statistics:
MT Count TotalSize Class Name
663a1fc8 1 12 System.Web.Configuration.ImpersonateTokenRef
79116758 1 20 Microsoft.Win32.SafeHandles.SafeTokenHandle
791037c0 1 20 Microsoft.Win32.SafeHandles.SafeFileMappingHandle
79103764 1 20 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle
6639c104 1 20 System.Web.PerfInstanceDataHandle
663f6b5c 1 28 System.Web.Security.FileSecurityDescriptorWrapper
663a105c 1 32 System.Web.Compilation.CompilationMutex
7910b630 2 40 System.Security.Cryptography.SafeProvHandle
79112728 5 100 Microsoft.Win32.SafeHandles.SafeWaitHandle
790fe704 2 112 System.Threading.Thread
7910a5c4 2 120 System.Runtime.Remoting.Contexts
...
Q:在這個命令的輸出中列出了什么對象? A:所有具有終結/析構器的都被注冊到終結器隊列中,當對象被垃圾收集時,終結器會運行析構函數,否則在dispose函數中終結過程會掛起。
Q:有多少個對象是出於“ready for finalization”,它是什么意思? A:大約有36000個,這些對象是要被垃圾收集的,正在等待被終結。如果ready for finalization大於0 但沒有顯示任何信息,這是一個說明終結器線程被堵塞的最好時機。所以這些對象被堵住了等待終結,他們消耗了大部分的內存。
2) 找出終結線程,了解它正在干什么,運行!threads ,在列出的線程中查找帶有“(Finalizer)”的線程。 3) 切換到終結線程,檢查托管的和本地(原生)的調用堆棧。 ~5s (把5 替換成真實的終結線程(finalizer thread)的ID號) kb 2000 !clrstack 0:000> !threads ...
20 2 1b94 001ac2c0 200b220 Enabled 00000000:00000000 001ccc80 0 MTA (Finalizer)
...
0:020> !clrstack
OS Thread Id: 0x1b94 (20)
ESP EIP
02a0f8fc 7d61cca8 [HelperMethodFrame: 02a0f8fc] System.Threading.Thread.SleepInternal(Int32)
02a0f950 0fe90ce8 Link.Finalize()
02a0fc1c 79fbcca7 [ContextTransitionFrame: 02a0fc1c]
02a0fcec 79fbcca7 [GCFrame: 02a0fcec]
Q:什么對象正在被終結? A:看起來是一個link 對象。 Q:它正在干什么? 為什么這個會導致高內存使用率? A:終結link對象的終結器線程因為sleep 被堵住了。意味着終結器被堵住,進程中沒有東西可以被終結。因而等待終結的進程都會仍然在內存中直到終結器醒來它們被終結為止。 |
示例6: 線程狀態
!threads命令看看當前CLR中有哪些線程正在執行
以下為引用:
0:004> !threads
ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
PreEmptive GC Alloc Lock
ID ThreadOBJ State GC Context Domain Count APT Exception
0 6ec 0014e708 6020 Enabled 00000000:00000000 00148a90 0 STA
2 a68 00157618 b220 Enabled 00000000:00000000 00148a90 0 MTA (Finalizer)
前面5個計數器分別表示托管(managed)線程、未啟動線程、后台線程、阻塞線程和僵死線程的數量。
下面的列表是當前托管線程的詳細信息:第一個域是WinDbg的線程編號;ID是Win32線程ID;ThreadObj是線程的對象;State是一個標志位,以后再詳細介紹;PreEmptive GC表示GC是否與此線程協作;GC Alloc Context是GC的相關信息;Domain是線程所在AppDomain;Lock Count是線程擁有鎖的計數器;APT是線程類型,沿用COM中STA/MTA/NTA(netural)的概念;最后的Exception表示線程類型,除了普通的用戶線程外還有finalizer、GC、Theadpool Worker和Threadpool Completion Port,其功能與名字相符.
示例7: 調試.net代碼
1. !name2ee SimpleSample.exe SimpleSample.Program.Main
顯示方法相關地址
0:004> !name2ee SimpleSample.exe SimpleSample.Program.Main
Module: 00982c5c (SimpleSample.exe)
Token: 0x06000005
MethodDesc: 00983000
Name: SimpleSample.Program.Main()
JITTED Code Address: 01220070
2. !dumpil 00983000
顯示方法被C#編譯器編譯之后的IL代碼
0:004> !dumpil 00983000
ilAddr = 004020c4
IL_0000: nop
IL_0001: ldstr "Any key continue... ... "
IL_0006: call System.Console::WriteLine
IL_000b: nop
IL_000c: call System.Console::Read
IL_0011: pop
IL_0012: call SimpleSample.Program::getcharBuffer
IL_0017: stloc.0
IL_0018: ldloc.0
IL_0019: call SimpleSample.Program::changeto4p
IL_001e: nop
IL_001f: ldloc.0
IL_0020: call System.Console::WriteLine
IL_0025: nop
IL_0026: call System.Console::Read
IL_002b: pop
IL_002c: call System.Console::Read
IL_0031: pop
IL_0032: ret
3. !u 01220070
顯示JIT編譯了的方法的本地代碼
Other:
!dumpmt -md 00983024 //得到類的成員函數詳細信息
!dumpheap -stat //顯示程序中所有對象的統計信息
!dumpheap -mt 00983024 //該命令顯示MethodTable的詳細信息
!gcroot 012919b8 //來顯示一個實例的所屬關系
!dumpobj(do) 012a3904 //顯示一個對象的具體內容
!ObjSize 012a1ba4 //對象實際在內存中的大小
!DumpArray
//查看數組信息 (http://www.pin5i.com/showtopic-15919.html)
!dumpheap -type Exception //查看異常信息
示例8: 查看方法代碼
!ip2md 05600dfd --05600dfd: 表示EIP
MethodDesc: 02429048
Method Name: DataLayer.GetFeaturedProducts()
Class: 055b18ac
MethodTable: 0242905c
mdToken: 06000008
Module: 024285cc
IsJitted: yes
m_CodeOrIL: 05600dd0
I.根據md來看:!dumpil 02429048 (這個地址是上面步驟f中的輸出的第一行
MethodDesc的值)
II. 根據native code來看:!u 05600dd0 (這個地址是上面步驟f中的輸出的最后一行的m_CodeOrIL的值)
III.根據module來看:!dumpmodule 024285cc (這個地址是上面步驟分鍾的輸出的
倒數第三行的Module的值)
附: WinDbg / SOS Cheat Sheet
Environment |
|
Attach to process |
F6 |
Detach from a process |
.detach |
Break debugger execution |
Ctrl-Break |
Continue debugger execution |
g |
Exit WinDbg |
q |
Clear the screen |
.cls |
Getting Help |
|
Debugger commands |
? |
Debugger commands |
.help |
Online help file |
.hh command |
Help on extension on top of chain |
!help |
Help on specific extension command |
!help command |
Issuing Commands |
|
Scroll through command history |
[up], [down], [enter] |
Paste into command window |
[right-click] |
Examining the Unmanaged Environment |
|
List loaded modules with full path |
lmf |
List loaded modules with last modified timestamp |
lmt |
List unmanaged threads |
~ |
Select active thread |
~thread_id s |
View call stack |
k |
View thread CPU consumption |
!runaway |
Set a breakpoint |
bp |
Dump small memory image |
.dump path |
Dump large memory image |
.dump /ma path |
Loading SOS |
|
Load SOS for .NET 1.x |
.load clr10\sos |
Load SOS for .NET 2.0 |
.loadby sos mscorwks |
Examining the Managed Environment |
|
Dump runtime type information |
!dumpruntimetypes |
View managed threads |
!threads |
View managed call stack |
!clrstack |
View combined managed / unmanaged callstack |
!dumpstack |
View function call arguments |
!clrstack –p |
View local variables |
!clrstack –l |
View object dump |
!do address |
View array dump |
!da address |
View object size (including children) |
!objsize address |
View heap usage by type |
!dumpheap -stat |
View heap usage filtered by type |
!dumpheap -type type |
View GC roots of object instance |
!gcroot address |
View managed sync blocks |
!syncblk |
View managed thinlocks (CLR 2.0) |
!dumpheap –thinlock |
View information on most recent exception |
!printexception |
Set a breakpoint |
!bpmd module method |
Type |
Explanation |
ESP |
ESP=Extended Stack Pointer, Object is in use on a stack |
DOMAIN(001CCE68):HANDLE(Strong) |
Strong reference, Typically a static variable |
DOMAIN(001CCE68):HANDLE(WeakLn) |
Weak Long Handle, A weak reference that is tracked through finalization (can be resurrected) |
DOMAIN(001CCE68):HANDLE(WeakSh) |
Weak Short Handle, A weak reference, can't be resurrected |
DOMAIN(001CCE68):HANDLE(Pinned) |
Pinned object, pinned at a specific address, can't move around during garbage collection. |
DOMAIN(001CCE68):HANDLE(RefCnt) |
Reference count, referenced as long as the reference count is > 0. |
第五章 sos.dll 擴展命令
命令 |
描述 |
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。 你能夠從: http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda 下載CLR簡檔器。 |
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欄的結果。 |
注:個人總結整理,如有指教問題請liudaoyu@outlook.com 謝謝!