一、簡介
Net 高級偵錯的相關文章,我自從學習了之後,以前很多模糊的地方現在很清楚了,原來自己的功力還是不夠,所以有很多不明白,透過學習 Net 高級偵錯,眼前豁然開朗,茅塞頓開。
其實,剛開始要學習【Net 高級偵錯】,還是很是很困難的,很多工具不會用,又不知道如何偵錯,痛苦的又很多次想放棄,但是,最終還是堅持下來,收獲也不小。
既然堅持下來了,我就把學習的過程記錄下來,也許以後自己的能用的到,可以方便查詢。或許,有其他人也有同樣的困擾,或授權以在我這裏得到一些幫助,有幫助我當然很開心。當然,Net 高級偵錯的路還很遠,我也是剛起步,不足之處太多,也希望大家原諒,有不對之處,歡迎指正。
偵錯環境
作業系統:Windows Professional 10
偵錯工具:Windbg Preview(可以去Microsoft Store 去下載)
開發工具:Visual Studio 2022
Net 版本:Net Framework 4.8
CoreCLR源碼:https://sourceforge.net/projects/coreclr.mirror/files/latest/download
二、偵錯工具介紹
俗話說得好,工欲善其事,必先利其器,我們要想偵錯程式,必須有很好的工具,如果連偵錯工具都沒有,那真就成了巧婦難為無米之炊。
所以,接下來,我先介紹一些偵錯工具,每種偵錯工具都有各自的用途。
測試程式碼
我們想要演示 Windbg 的使用過程,使用方法,偵錯程式的各種問題,必須有程式作為載體,由於這是【Net 高級偵錯】的第一節課,所以只是簡單的演示一下,例子程式碼沒有實際的作用,作為演示還是夠了的。
本節有兩分程式碼,分別是:Example_1_1_1和 Example_1_1_2
Example_1_1_1的程式碼如下:
namespaceExample_1_1_1
{
internal classProgram
{
staticvoidMain(string[] args)
{
Console.WriteLine("Hello World");
Console.ReadLine();
}
}
}
Example_1_1_2的程式碼如下:
namespaceExample_1_1_2
{
internal classProgram
{
privatestatic IList<byte[]> list=new List<byte[]>();
staticvoidMain(string[] args)
{
Task.Run(() =>
{
for (int i = 0; i < int.MaxValue; i++)
{
list.Add(newbyte[10000]);
if (i % 10 == 0)
{
list[i] = null;
}
Console.WriteLine($"當前索引 Index={i}");
}
});
Console.ReadLine();
}
}
}
2.1、SOS
【SOS 偵錯擴充套件】允許我們檢視有關在 CLR 內執行的程式碼的資訊。
例如,可以使用 【SOS 偵錯擴充套件】顯示有關【托管堆】的資訊、尋找堆損壞情況、顯示【執行時】所使用的內部數據型別以及檢視有關在【執行時】內執行的所有受控代碼的資訊。
它就是一個 dll,包含一組存取 CLR 內部數據的介面函式,可以使我們使用 Windbg 偵錯程式偵錯 Net 程式,解決程式問題的時候更簡單。
Windbg-----------------SOS------------CLR,這是一個有關SOS的示意圖,SOS的作用就像一個中介者一樣,Windbg可以透過 SOS 來偵錯 CLR。
2.1.1、檔位置
這個程式集是隨.NET Framework一起安裝的,一般不需要單獨安裝。SOS 偵錯擴充套件是有2個版本的,分別是32位元和64位元,安裝的位置如下
32位元安裝位置:C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll
64位元安裝位置:C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll
2.1.2、如何載入
Windbg Preview 是不用單獨執行載入的工作的,它會自動載入它所需要的版本,如果是老版本的 Windbg,比如:windbg10 ,可以透過 .load 命令載入 SOS.dll。
一般情況,使用windbg內建的命令【.load sos】即可自動載入,使用【.chain】檢視載入是否成功。如果沒有載入 SOS.dll,我們可以手動載入,執行如下命令:
0:000> .load C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll
我們可以透過【.chain】命令檢查是否成功載入 SOS.dll。紅色字型顯示已經載入了 SOS 偵錯擴充套件。
0:000> .chain
Extension DLL search Path:
C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\WINXP;C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\winext;C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\winext\arcade;C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\pri;C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86;C:\Users\Administrator\AppData\Local\Dbg\EngineExtensions32;C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86;C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\amd64;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Microsoft SQL Server\150\Tools\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\Program Files\dotnet\;D:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\;D:\Program Files\Microsoft SQL Server\100\Tools\Binn\;D:\Program Files\Microsoft SQL Server\100\DTS\Binn\;D:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\;C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\;D:\Program Files (x86)\Microsoft SQL Server\100\DTS\Binn\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;D:\XIMEA\API;C:\XIMEA\API;D:\Program Files\Git\cmd;C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps;C:\Users\Administrator\.dotnet\tools
Extension DLL chain:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll: image 4.8.4300.0, API 1.0.0, built Thu Oct 8 08:41:14 2020
[path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll]
JsProvider: image 10.0.25877.1004, API 0.0.0,
[path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\winext\JsProvider.dll]
DbgModelApiXtn: image 10.0.25877.1004, API 0.0.0,
[path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\winext\DbgModelApiXtn.dll]
F:\Software\DebugTools\SOS\SOSEX\sosex_32\sosex.dll: image 4.5.0.0, API 1.0.0, built Fri Mar 7 23:17:26 2014
[path: F:\Software\DebugTools\SOS\SOSEX\sosex_32\sosex.dll]
CLRComposition: image 10.0.25877.1004, API 0.0.0,
[path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\winext\CLRComposition.dll]
wow64exts: image 10.0.25877.1004, API 1.0.0,
[path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\WINXP\wow64exts.dll]
dbghelp: image 10.0.25877.1004, API 10.0.6,
[path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\dbghelp.dll]
exts: image 10.0.25877.1004, API 1.0.0,
[path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\WINXP\exts.dll]
uext: image 10.0.25877.1004, API 1.0.0,
[path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\winext\uext.dll]
ntsdexts: image 10.0.25877.1004, API 1.0.0,
[path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2306.14001.0_x64__8wekyb3d8bbwe\x86\WINXP\ntsdexts.dll]
2.1.3、如何使用
說到是第一節講 Windbg 使用的文章,所以具體的使用步驟還是要說明的詳細一點。
程式碼案例:Example_1_1_1
1)、載入程式集
A、編譯程式源碼,生成 Dll 或者是 Exe 程式集,可以在拷貝地址,當然這是我的習慣,你可以選擇 Windbg 尋找檔也是可以的。
B、開啟 Windbg 偵錯程式。透過選單選擇【檔】-->【launch executable】,彈出視窗,找到指定的程式集檔,選擇開啟,就進入了 Windbg 偵錯程式頁面,是暫停的狀態,此時,就可以根據自己的需要,選擇下一步的操作。
2)我們執行一些命令,來一個直觀感覺。
A、.cls 剛進來,內容太多,可以清楚一下螢幕。
【Debuggee is running】其實這裏是停在了 Console.ReadLine();這行程式碼這裏,點選【Break】按鈕,我們就行偵錯了。
D、~os 切換到主執行緒。
0:001> ~0s
eax=00000000 ebx=000000a4 ecx=00000000 edx=00000000 esi=004ff10c edi=00000000
eip=773410fc esp=004feff4 ebp=004ff054 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
ntdll!NtReadFile+0xc:
773410fc c22400 ret 24h
E、!sos.help 我們可以檢視 SOS 的所有命令。
0:000> !sos.help
-------------------------------------------------------------------------------
SOS is a debugger extension DLL designed to aid in the debugging of managed
programs. Functions are listed by category, then roughly in order of
importance. Shortcut names for popular functions are listed in parenthesis.
Type "!help <functionname>"for detailed info on that function.
Object Inspection Examining code and stacks
----------------------------- -----------------------------
DumpObj (do) Threads
DumpArray (da) ThreadState
DumpStackObjects (dso) IP2MD
DumpHeap U
DumpVC DumpStack
GCRoot EEStack
ObjSize CLRStack
FinalizeQueue GCInfo
PrintException (pe) EHInfo
TraverseHeap BPMD
COMState
Examining CLR data structures Diagnostic Utilities
----------------------------- -----------------------------
DumpDomain VerifyHeap
EEHeap VerifyObj
Name2EE FindRoots
SyncBlk HeapStat
DumpMT GCWhere
Dump class ListNearObj (lno)
DumpMD GCHandles
Token2EE GCHandleLeaks
EEVersion FinalizeQueue (fq)
DumpModule FindAppDomain
ThreadPool SaveModule
DumpAssembly ProcInfo
DumpSigElem StopOnException (soe)
DumpRuntimeTypes DumpLog
DumpSig VMMap
RCWCleanupList VMStat
DumpIL MinidumpMode
DumpRCW AnalyzeOOM (ao)
DumpCCW
Examining the GC history Other
----------------------------- -----------------------------
HistInit FAQ
HistRoot
HistObj
HistObjFind
HistClear
F、!dumpheap -stat 我們可以檢視托管堆。
0:000> !dumpheap -stat
Statistics:
MT Count TotalSize class Name
6f545468 1 12 System.Collections.Generic.GenericEqualityComparer`1[[System.String, mscorlib]]
6f544888 1 12 System.Security.HostSecurityManager
6f543d78 1 12 System.Collections.Generic.ObjectEqualityComparer`1[[System.Type, mscorlib]]
6f5a9b0c 1 16 System.IO.TextReader+SyncTextReader
......
6f545c40 3 806 System.Byte[]
6f542c60 10 2986 System.Char[]
6f5424e4 166 6100 System.String
6f542788 6 17748 System.Object[]
Total 332 objects
G、!eeheap -gc 我們可以檢視托管堆的布局。
0:000> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x024d1018
generation 1 starts at 0x024d100c
generation 2 starts at 0x024d1000
ephemeral segment allocation context: none
segment begin allocated size
024d0000 024d1000 024d5ff4 0x4ff4(20468)
Large object heap starts at 0x034d1000
segment begin allocated size
034d0000 034d1000 034d5558 0x4558(17752)
Total Size: Size: 0x954c (38220) bytes.
------------------------------
GC Heap Size: Size: 0x954c (38220) bytes.
H、.hh 命令可以檢視命令的幫助文件。
2.2、SOSEX
SOSEX 這款 dll 也是分兩個版本的,分別是:32位元和64位元。但是說明一下,這個版本只能使用 Net Framework 環境下,Net Core,Net5、Net6、Net7等以上不能使用的。下載地址就不貼了,上網一找,也不難。SOSEX 是 SOS 非常有力的擴充套件,提供了非常多的實用函式。**
1)、測試程式碼
Example_1_1_1
2)、簡單命令的執行
A、 !sosex.help* 檢視 SOSEX的幫助命令
0:000> !sosex.help
SOSEX - Copyright 2007-2014 by Steve Johnson - http://www.stevestechspot.com/
To report bugs or offer feedback about SOSEX, please email [email protected]
Quick Ref:
--------------------------------------------------
bhi [filename] BuildHeapIndex - Builds an index file for heap objects.
bpsc (Deprecated. Use !mbp instead)
chi ClearHeapIndex - Frees all resources used by the heap index and removes it from memory.
dlk [-d] Displays deadlocks between SyncBlocks and/or ReaderWriterLocks
dumpfd <FieldAddr> Dumps the properties of a FieldDef structure
dumpgen <GenNum> [-free] [-stat] [-type <TYPE_NAME>] Dumps the contents of the specified generation
[-nostrings]
finq [GenNum] [-stat] Displays objects in the finalization queue
frq [-stat] Displays objects in the Freachable queue
gcgen <ObjectAddr> Displays the GC generation of the specified object
gch [HandleType]... [-stat] Lists all GCHandles, optionally filtered by specified handle types
help [CommandName] Display this screen or details about the specified command
lhi [filename] LoadHeapIndex - load the heap index into memory.
mbc <SOSEX breakpoint ID | *> Clears the specified or all managed breakpoints
mbd <SOSEX breakpoint ID | *> Disables the specified or all managed breakpoints
mbe <SOSEX breakpoint ID | *> Enables the specified or all managed breakpoints
mbl [SOSEX breakpoint ID] Prints the specified or all managed breakpoints
mbm <Type/MethodFilter> [ILOffset] [Options] Sets a managed breakpoint on methods matching the specified filter
mbp <SourceFile> <nLineNum> [ColNum] [Options] Sets a managed breakpoint at the specified source code location
mdso [Options] Dumps object references on the stack and in CPU registers in the current context
mdt [TypeName | VarName | MT] [ADDR] [Options] Displays the fields of an object or type, optionally recursively
mdv [nFrameNum] Displays arguments and locals for a managed frame
mfrag [-stat] [-mt:<MT>] Reports free blocks, the type of object following the free block, and fragmentation statistics
mframe [nFrameNum] Displays or sets the current managed frame for the !mdt and !mdv commands
mgu // TODO: Document
mk [FrameCount] [-l] [-p] [-a] Prints a stack trace of managed and unmanaged frames
mln [expression] Displays the type of managed data located at the specified address or the current instruction pointer
mlocks [-d] Lists all managed lock objects and Criticalps and their owning threads
mroot <ObjectAddr> [-all] Displays GC roots for the specified object
mt (no parameters) Steps into the managed method at the current position
mu [address] [-s] [-il] [-n] Displays a disassembly around the current instruction with interleaved source, IL and asm code
muf [MD Address | Code Address] [-s] [-il] [-n] Displays a disassembly with interleaved source, IL and asm code
mwaits [-d | LockAddr] Lists all waiting threads and, if known, the locks they are waiting on
mx <Filter String> Displays managed type/field/method names matching the specified filter string
rcw [Object or SyncBlock Addr] Displays Runtime Callable Wrapper (RCW) COM interop data.
refs <ObjectAddr> [-target|-source] Displays all references from and to the specified object
rwlock [ObjectAddr | -d] Displays all RWLocks or, if provided a RWLock address, details of the specified lock
sosexhelp [CommandName] Display this screen or details about the specified command
strings [ModuleAddress] [Options] Search the managed heap or a module for strings matching the specified criteria
ListGcHandles - See gch
Use !help <command> or !sosexhelp <command> for more details about each command.
You can also use the /? (or -?) option on any command to get helpfor that command.
B、!strings 我們可以把行程中所有的字串找出來。
0:000> !strings
Address Gen Length Value
---------------------------------------
024d1228 0 0
024d1254 0 121 E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\AdvancedDebug.NetFramework.Example_1_1_1\bin\Debug\
024d1354 0 145 E:\Visual Studio 2022\Source\Projects
......
024d34c0 0 3 Nov
024d34d4 0 3 Dec
024d3698 0 6 zh-CHS
024d36b4 0 6 zh-CHT
024d36d0 0 5 zh-CN
024d3764 0 5 zh-cn
024d3924 0 5 zh-CN
......
024d3cf8 0 3 936
024d3d0c 0 1 3
024d3d1c 0 1 2
024d3d2c 0 1 0
024d3d3c 0 1 0
024d3d4c 0 24 NLS_CodePage_936_3_2_0_0
024d3e2c 0 8 encoding
024d3e4c 0 6 stream
024d42bc 0 5 bytes
024d42d4 0 5 chars
024d42ec 0 9 charCount
024d430c 0 9 charIndex
024d432c 0 9 byteCount
024d4a9c 0 5 count
024d4ab4 0 6 offset
---------------------------------------
166 strings
C、!finq 可以檢視終端子佇列。
0:000> !finq
Generation 0:
Address Size Type
---------------------------------------------
024d1e34 20 Microsoft.Win32.SafeHandles.SafePEFileHandle
024d24d8 44 System.Threading.ReaderWriterLock
024d2638 20 Microsoft.Win32.SafeHandles.SafeFileHandle
024d3d8c 20 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle
024d3da0 20 Microsoft.Win32.SafeHandles.SafeFileMappingHandle
024d4a30 52 System.Threading.Thread
024d4ad0 20 Microsoft.Win32.SafeHandles.SafeFileHandle
7 objects, 196 bytes
Generation 1:
Address Size Type
---------------------------------------------
0 objects, 0 bytes
Generation 2:
Address Size Type
---------------------------------------------
0 objects, 0 bytes
TOTAL: 7 objects, 196 bytes
D、!mlocks 判斷當前是否有死結。
0:000> !mlocks
Examining SyncBlocks...
Scanning for ReaderWriterLock instances...
Scanning for holders of ReaderWriterLock locks...
Scanning for ReaderWriterLockSlim instances...
Scanning for holders of ReaderWriterLockSlim locks...
Examining Criticalps...
ClrThread DbgThread OsThread LockType Lock LockLevel
----------------------------------------------------------------------
0x1 0 0x1028 thinlock 024d4e90 (recursion:0)
2.3、Net 反編譯工具
Net 反編譯器可以編譯 IL 程式碼,讓 IL 程式碼轉成 C# 程式碼,這裏推薦兩款工具。
2.3.1、ILSpy
官網地址:https://github.com/icsharpcode/ILSpy
映像地址:https://sourceforge.net/projects/ilspy.mirror/files/latest/download
2.3.2、DnSpy
這個工具不僅可以可以反編譯 C# 程式碼,還可以對 Net Framework 程式進行偵錯。
官網地址:https://github.com/dnSpy/dnSpy/releases
其他下載:https://filehippo.com/zh/download_dnspy/
2.4、PerfView
這是 CLR 團隊調優 CLR 使用的工具,可以即時監控程式的行為,比如:程式的 GC 觸發的情況。
官網地址:https://github.com/microsoft/perfview
微軟官網:https://www.microsoft.com/en-us/download/details.aspx?id=28567
1)、測試程式碼
Example_1_1_2
2)、使用 Perfview 監控程式。
Perfview使用很簡單,先開啟 Perfview 軟體,然後電機選單【collect】--->【collect】,開啟【Collecting data over a user specified interval】視窗,什麽也不用選擇,直接點選視窗中的【Start Collection】按鈕,開始采集數據。
當 Perfview 開始采集數據的時候,我們開啟我們的測試程式【Example_1_1_2.exe】,執行到10000,關閉程式,點選【StopCollection】按鈕。Perfview 開始生成數據,可以觀察狀態列,檢視 Perfview 的動作。
還有很多數據,不能一一展示,大家可以自己動手測試下。我截了一張圖,表示一下。
三、結束
站在高人的肩膀之上,自己輕松了很多,但是,自己還是一個小學生,Net 高級偵錯這條路,也剛剛起步,還有很多要學的地方。
轉自:可均可可
連結:cnblogs.com/PatrickLiu/p/17781974.html
- EOF -
技術群:
添加小編微信並備註進群
小編微信:mm1552923
公眾號:dotNet編程大全