有時候我們想查看一個正在運行的程序內存中的數據,可以在任務管理器將內存狀態保存為轉儲文件,並使用WinDBG驗證,這里我們來試試:
0.安裝WinDBG
1.首先寫個代碼用來測試
一個class
public class MyClass
{
public int AintValue = 123;
public static int BintValue = 456;
public string AstringValue = "AAA";
public static string BstringValue = "BBB";
}
在main中引用
Console.WriteLine($"ret={d1(1)}");
MyClass MC = new MyClass();
MC.AstringValue = "SuperAAAA";
Console.ReadKey(true);//程序會停在這,這時候保存文件
Console.Write(MC.AstringValue);
2.編譯運行以后,到任務管理器保存內存轉儲文件
3.用WinDBG打開轉儲文件
點這里:
這里,然后選文件:
這里需要注意的是:
32位的WinDBG用來調試32位的程序dump文件,
64位的WInDBG用來調試64位的程序dump文件,
如果你跟我一樣用的是UWP版的WinDBG,那只能調試64位的(一定有辦法能調32位的,但我不知道,如果你知道,請回復,感謝~)
4:在內存中搜索我們要查看的對象類型
我們可以看到中間有個命令輸入框:
首先輸入兩個命令,加載兩個.net調試相關文件:
.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll
.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
notice:中間有個目錄是Framework64,如果是調試32位程序,改為Framework
加載成功.
在上面的C#代碼中,我們聲明了一個類 MyClass ,並實例化了它,現在我們要找到它,在windbg里,搜索類有兩種方式:
1:根據類名 (有可能重復)
2:根據MT(Methot Table,唯一)
剛開始是不知道MT的,所以根據類名搜索:
!dumpheap -type MyClass
notice:"!dumpheap -type"這部分不驗證大小寫,后面類名會驗證大小寫
返回的內容,第一塊是類的實例列表,第二塊是對象列表(有時候名字很像的對象也會在這里)
可以看到我們的對象只有一個,第一列是MT,如果你搜索出了多個,可以根據MT搜索:
!DumpHeap -mt 00007ff9fc0a7488
5:查看對象信息
從實例列表中可以看到這個類只有1個實例,數據格式是:
內存地址 MT 占用內存長度
我們可以從內存地址,查看這個實例的詳細信息:
!DumpObj /d 000002331f11bed0
notice:DumpObj 可以簡寫為do
可以看到下面列出了對象的所有屬性.包括靜態的,動態的.
值類型的屬性直接顯示了值
引用類型的屬性給出了引用地址
對於string類型,我們還要再進一步:
!DumpObj 000002331f112f18
就可以看到字符串值了,如果是byte[]數據,可以直接用 "dd 內存起點 內存終點" 進行查看,如果想解析成字符串可以用du命令(u表示按unicode解析)
dd 000002331f112f18+c 000002331f112f18+c+53
du 000002331f112f18+c 000002331f112f18+c+8
字符串數據前12個字節是字符串的屬性,所以要過掉