Net 高級調試之十六:平臺互用性及P/Invoke和內存泄漏調試

一、簡介
    今天是《Net 高級調試》的第十六篇文章,也是這個系列的最後一篇文章了既然是最後一篇文章,我需要在這裏說明一下,我當前的這個系列,不是針對《Net 高級調試》這本書來的,而是根據“一線碼農”的視頻做的這個系列。當然了,他的視頻是根據《Net 高級調試》這本書來的,內容上做了一些調整,可以說是與時俱進的。說實在的,我第一次看《Net 高級調試》這個本書是蒙的,不知道從何處入手,有一個視頻帶我入門,相對而言是更容易下一下。入門之後,在深入研究《Net 高級調試這個本書》。好了廢話就說這麼多。今天是這個系列的最後一章,主要說一下【互用性】調試相關的內容,比如:P/Invoke調用的調試,互操作中的內存泄漏,COM互用性中終結操作的調試。我們寫 C# 代碼的,有時候也會用到P/Invoke調用的,多積累點經驗是好事,我們可以做到有事不怕事,來者不拒。這些底層的東西,肯定不是一次就能接受的,所以,我們需要多次調試,才能慢慢體會其中之意,俗話說的好,書讀千遍,其意自現。
     如果在沒有說明的情況下,所有代碼的測試環境都是 Net Framewok 4.8,但是,有時候爲了查看源碼,可能需要使用 Net Core 的項目,我會在項目章節裏進行說明。好了,廢話不多說,開始我們今天的調試工作。

       調試環境我需要進行說明,以防大家不清楚,具體情況我已經羅列出來。
          操作系統:Windows Professional 10
          調試工具:Windbg Preview(可以去Microsoft Store 去下載)
          開發工具:Visual Studio 2022
          Net 版本:Net Framework 4.8
          CoreCLR源碼:源碼下載

二、基礎知識
    1、平臺調用 P/Invoke

        1.1、簡介
            平臺調用服務 P/Invoke 是 CLR 的一部分,負責確保託管代碼可以調用從非託管程序集中導出的各種函數,原因很簡單,託管類型參數和非託管類型參數是不一致的,比如:託管的引用類型是帶有附加信息的,二非託管類型是不可能有的。

    2、P/Invoke 的崩潰
        2.1、調用協定引發的崩潰。
            很多時候調用協定不一致容易造成程序的崩潰,這種問題需要通過【調試器】檢查。

        2.2、委託異步引發的崩潰
            【託管代碼】到【非託管代碼】的切換過程中,對象的固定是有 P/Invoke 層全權負責的,但是這個固定的範圍這個同步的 Request-Response 週期,如果超過請求相應週期,那就容易出現各種問題,比如:Example_16_1_4。

        2.3、非託管內存泄漏
            非託管內存泄露,這裏就不多說,我們舉例說明,直接看調試代碼。(這個方案沒有完全解決,有些命令沒有執行結果。

三、源碼調試
    廢話不多說,這一節是具體的調試過程,又可以說是眼見爲實的過程,在開始之前,我還是要囉嗦兩句,這一節分爲兩個部分,第一部分是測試的源碼部分,沒有代碼,當然就談不上測試了,調試必須有載體。第二部分就是根據具體的代碼來證實我們學到的知識,是具體的眼見爲實。

    1、項目源碼
        1.1、Example_16_1_1

 1 using System;
 2 using System.Diagnostics;
 3 using System.Runtime.InteropServices;
 4 
 5 namespace Example_16_1_1
 6 {
 7     internal class Program
 8     {
 9         /// <summary>
10         /// 
11         /// </summary>
12         /// <param name="freq"></param>
13         /// <param name="dur"></param>
14         /// <returns></returns>
15         [DllImport("Kernel32.dll", SetLastError = true)]
16         private static extern bool Beep(uint freq, uint dur);
17 
18 
19         static void Main(string[] args)
20         {
21             Debugger.Break();
22 
23             Beep(1000, 1000);
24 
25             Console.ReadLine();
26         }
27     }
28 }
View Code


        1.2、Example_16_1_2

 1 using System;
 2 using System.Runtime.InteropServices;
 3 
 4 namespace Example_16_1_2
 5 {
 6     internal class Program
 7     {
 8         [DllImport("Example_16_1_3.dll", CallingConvention = CallingConvention.ThisCall, CharSet = CharSet.Unicode)]
 9         //[DllImport("Example_16_1_3.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
10         public static extern void Alloc(string str);
11         static void Main(string[] args)
12         {
13             var str = "hello world";
14 
15             Alloc(str);
16 
17             Console.ReadLine();
18         }
19     }
20 }
View Code


        1.3、Example_16_1_3(C++項目)

 1 // Example_16_1_3.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
 2 
 3 extern "C"
 4 {
 5     __declspec(dllexport) void Alloc(wchar_t* c);
 6 }
 7 
 8 #include "iostream"
 9 #include <Windows.h>
10 
11 using  namespace std;
12 
13 void Alloc(wchar_t* c)
14 {
15     wprintf(L"%s \n", c);
16 }
View Code


        1.4、Example_16_1_4

 1 using System;
 2 using System.Runtime.InteropServices;
 3 
 4 namespace Example_16_1_4
 5 {
 6     internal class Program
 7     {
 8         public delegate void Callback(uint i);
 9         static void Main(string[] args)
10         {
11             Test();
12             GC.Collect(); //不出問題的情況。
13             Console.ReadLine();
14         }
15 
16         //static GCHandle handle;
17         private static void Test()
18         {
19             Callback callback = MyRun;
20 
21             //handle=GCHandle.Alloc(callback, GCHandleType.Normal);
22             AsyncProcess(callback);
23 
24             callback = null;
25         }
26 
27         private static void MyRun(uint i)
28         {
29             Console.WriteLine("這是非託管代碼回調我的實現!");
30         }
31 
32         private static void MyCallback(string result)
33         {
34             Console.WriteLine($"Result={result}");
35         }
36 
37         [DllImport("Example_16_1_5", CallingConvention = CallingConvention.StdCall)]
38         private static extern void AsyncProcess(Callback callback);
39     }
40 }
View Code


        1.5、Example_16_1_5(C++項目)

 1 // Example_16_1_5.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
 2 //
 3 
 4 #include <iostream>
 5 #include <Windows.h>
 6 
 7 using namespace std;
 8 
 9 typedef void(__stdcall* PCallback)(UINT result);
10 
11 extern "C"
12 {
13     _declspec(dllexport) void __stdcall AsyncProcess(PCallback ptr);
14 }
15 
16 DWORD WINAPI ThreadWorkItem(LPVOID lpParameter)
17 {
18     printf("我是非託管的工作線程,tid=%d \n", GetCurrentThreadId());
19 
20     Sleep(2000);
21 
22     PCallback callback = (PCallback)lpParameter;
23 
24     callback(0);
25 
26     return 0;
27 }
28 
29 void __stdcall AsyncProcess(PCallback ptr)
30 {
31     HANDLE hThread = CreateThread(NULL, 0, ThreadWorkItem, ptr, 0, NULL);
32 }
View Code


        1.6、Example_16_1_6

 1 using System;
 2 using System.Runtime.InteropServices;
 3 using System.Threading.Tasks;
 4 
 5 namespace Example_16_1_6
 6 {
 7     internal class Program
 8     {
 9         [DllImport("Example_16_1_7", CallingConvention = CallingConvention.StdCall)]
10         private static extern int InitData(int len);
11 
12         static void Main(string[] args)
13         {
14             var task = Task.Factory.StartNew(() =>
15             {
16                 for (int i = 0; i < int.MaxValue; i++)
17                 {
18                     InitData(10000);
19 
20                     Console.WriteLine($"i={i} 次操作!");
21                 }
22             });
23 
24             Console.ReadLine();
25         }
26     }
27 }
View Code


        1.7、Example_16_1_7(C++項目)

 1 // Example_16_1_7.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
 2 //
 3 
 4 #include <iostream>
 5 #include <Windows.h>
 6 
 7 using namespace std;
 8 
 9 extern "C"
10 {
11     _declspec(dllexport) int __stdcall InitData(int len);
12 }
13 
14 int __stdcall InitData(int len) {
15     char* c = new char[len];
16     return 1;
17 }
View Code

        

    2、眼見爲實
        項目的所有操作都是一樣的,所以就在這裏說明一下,但是每個測試例子,都需要重新啓動,並加載相應的應用程序,加載方法都是一樣的。流程如下:我們編譯項目,打開 Windbg,點擊【文件】----》【launch executable】附加程序,打開調試器的界面,程序已經處於中斷狀態。

        我們需要使用【g】命令,繼續運行程序,然後到達指定地點停止後,我們可以點擊【break】按鈕,就可以調試程序了。有時候可能需要切換到主線程,可以使用【~0s】命令。

        2.1、如何觀察 P/Invoke 是CLR的一部分。
            調試源碼:Example_16_1_1
            因爲【Beep】是Windows 提供的蜂鳴函數,可以直接用【bp】命令下斷點,過了這麼多年,這個函數的名稱也有了變化,現在是【KERNEL32!BeepImplementation】。
            當我們進入 Windbg 調試器界面後,我們使用【x】命令,查找一下【Beep】這個函數。

1 0:000> x kernel32!*beep*
2 7771194c          KERNEL32!_imp__Beep = <no type information>
3 776c0660          KERNEL32!BeepImplementation (_BeepImplementation@8)

            然後我們在這個方法上下斷點,通過【bp KERNEL32!BeepImplementation 】命令下斷點,然後繼續【g】運行調試器。

 1 0:000> bp KERNEL32!BeepImplementation
 2 0:000> g
 3 ModLoad: 75760000 757d9000   C:\Windows\SysWOW64\ADVAPI32.dll
 4 ModLoad: 76de0000 76e9f000   C:\Windows\SysWOW64\msvcrt.dll
 5 ModLoad: 75a10000 75a85000   C:\Windows\SysWOW64\sechost.dll
 6 ModLoad: 754c0000 7557a000   C:\Windows\SysWOW64\RPCRT4.dll
 7 ModLoad: 750f0000 7517d000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll
 8 ModLoad: 75ed0000 75f15000   C:\Windows\SysWOW64\SHLWAPI.dll
 9 ModLoad: 76400000 7640f000   C:\Windows\SysWOW64\kernel.appcore.dll
10 ModLoad: 75340000 75348000   C:\Windows\SysWOW64\VERSION.dll
11 ModLoad: 74740000 74ef0000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
12 ModLoad: 75a90000 75c24000   C:\Windows\SysWOW64\USER32.dll
13 ModLoad: 75f90000 75fa8000   C:\Windows\SysWOW64\win32u.dll
14 ModLoad: 739c0000 73a6b000   C:\Windows\SysWOW64\ucrtbase_clr0400.dll
15 ModLoad: 73a70000 73a84000   C:\Windows\SysWOW64\VCRUNTIME140_CLR0400.dll
16 ModLoad: 75c30000 75c53000   C:\Windows\SysWOW64\GDI32.dll
17 ModLoad: 76410000 764eb000   C:\Windows\SysWOW64\gdi32full.dll
18 ModLoad: 76360000 763db000   C:\Windows\SysWOW64\msvcp_win.dll
19 ModLoad: 755a0000 756c0000   C:\Windows\SysWOW64\ucrtbase.dll
20 ModLoad: 75fb0000 75fd5000   C:\Windows\SysWOW64\IMM32.DLL
21 ModLoad: 760d0000 76350000   C:\Windows\SysWOW64\combase.dll
22 (ef0.18fc): Unknown exception - code 04242420 (first chance)
23 ModLoad: 72340000 7374e000   C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\218db16dceaef380c6daf35c6a48f313\mscorlib.ni.dll
24 ModLoad: 75890000 75973000   C:\Windows\SysWOW64\ole32.dll
25 ModLoad: 760d0000 76350000   C:\Windows\SysWOW64\combase.dll
26 ModLoad: 764f0000 7654c000   C:\Windows\SysWOW64\bcryptPrimitives.dll
27 ModLoad: 71c00000 71c8a000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll
28 ModLoad: 770d0000 7716b000   C:\Windows\SysWOW64\OLEAUT32.dll
29 (ef0.18fc): Break instruction exception - code 80000003 (first chance)
30 eax=00f3f358 ebx=00000000 ecx=01045e60 edx=00f3f530 esi=02f524d4 edi=00f3f39c
31 eip=75e0f262 esp=00f3f2f0 ebp=00f3f37c iopl=0         nv up ei pl zr na pe nc
32 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
33 KERNELBASE!wil::details::DebugBreak+0x2:
34 75e0f262 cc              int     3

            這個斷點,還沒有到我們的Beep方法,到了【Debugger.Break();】這行代碼,然後,我們繼續【g】。

1 0:000> g
2 Breakpoint 0 hit
3 eax=776c0660 ebx=00f3f460 ecx=74813ac3 edx=00000000 esi=01045e60 edi=00f3f3d0
4 eip=776c0660 esp=00f3f340 ebp=00f3f3a4 iopl=0         nv up ei pl zr na pe nc
5 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
6 KERNEL32!BeepImplementation:
7 776c0660 8bff            mov     edi,edi

            紅色標註的就是我們想要斷住的方法。到了這裏,我們看看當前的調用棧,使用【!clrstack】命令。

1 0:000> !clrstack
2 OS Thread Id: 0x18fc (0)
3 Child SP       IP Call Site
4 00f3f350 776c0660 [InlinedCallFrame: 00f3f350] 
5 00f3f34c 02db092d DomainBoundILStubClass.IL_STUB_PInvoke(UInt32, UInt32)
6 00f3f350 02db087a [InlinedCallFrame: 00f3f350] Example_16_1_1.Program.Beep(UInt32, UInt32)
7 00f3f3ac 02db087a Example_16_1_1.Program.Main(System.String[]) [E:\Visual Studio 2022\...\Example_16_1_1\Program.cs @ 23]
8 00f3f530 7474f036 [GCFrame: 00f3f530] 

            InlinedCallFrame: 00f3f350 這樣有一個地址,就是一個棧針,這個棧針就是 CLR 裏面的部分,這個棧針地址就會調用 LoadLibrary方法,加載【Kernel32.dll】,如果加載了這個dll,就不需要在加載了,如果沒有加載才加載。加載了 dll 找到 Beep 方法的方發表,調用執行就可以了。

            我們可以使用【dp】命令查看一下這個指針。我執行了兩次,大家不用這樣執行。選擇自己喜歡的。

 1 0:000> dp 00f3f350
 2 00f3f350  7474fd74 00f3f530 00000008 00f3f344
 3 00f3f360  02db092d 00f3f3a4 02d24d58 01045e60
 4 00f3f370  00f3f310 00f3f3d0 776c0660 ffffffff
 5 00f3f380  747ff800 000003e8 000003e8 00000000
 6 00f3f390  000003e8 000003e8 00f3f460 00000000
 7 00f3f3a0  00f3f3d0 00f3f3b8 02db087a 00000000
 8 00f3f3b0  00000000 02f524c8 00f3f3c4 7474f036
 9 00f3f3c0  01045e60 00f3f418 747522da 00f3f460
10 0:000> dp 00f3f350 L1
11 00f3f350  7474fd74

            然後,我們在使用【ln 7474fd74】命令,查看具體詳情。

1 0:000> ln 7474fd74
2 Browse module
3 Set bu breakpoint
4 
5 (7474fd74)   clr!InlinedCallFrame::`vftable'   |  (7474fdc0)   clr!HelperMethodFrame_1OBJ::`vftable'
6 Exact matches:

            當然,我們也可以使用【u】命令,查看 clr!InlinedCallFrame 方法的源碼。當然,這個源碼是彙編源碼。

 1 0:000> u 7474fd74
 2 clr!InlinedCallFrame::`vftable':
 3 7474fd74 30a1757490ba    xor     byte ptr [ecx-456F8B8Bh],ah
 4 7474fd7a 7574            jne     clr!HelperMethodFrame_1OBJ::`vftable'+0x30 (7474fdf0)
 5 7474fd7c b019            mov     al,19h
 6 7474fd7e 7574            jne     clr!HelperMethodFrame_1OBJ::`vftable'+0x34 (7474fdf4)
 7 7474fd80 1061a0          adc     byte ptr [ecx-60h],ah
 8 7474fd83 7460            je      clr!HelperMethodFrame_1OBJ::`vftable'+0x25 (7474fde5)
 9 7474fd85 f9              stc
10 7474fd86 7f74            jg      clr!HelperMethodFrame_1OBJ::`vftable'+0x3c (7474fdfc)


        2.2、調用協定造成的崩潰。
            調試源碼:Example_16_1_2 和 Example_16_1_3(C++)
            我們【Example_16_1_2】項目的 Program 類聲明瞭一個Alloc方法,是C++ 的。這個方法的調用協定就是【CallingConvention = CallingConvention.Cdecl、CallingConvention.StdCall、CallingConvention.ThisCall】這個3中協定都是正常執行的,說明一下:和視頻中使用【CallingConvention.ThisCall】協定程序會崩潰是不一致的,本人親測,傳遞字符的規格是【CharSet = CharSet.Unicode】,也就是雙字節。
            我們的C++項目【Example_16_1_3】的【Example_16_1_3.cpp】類就定義了 Alloc 方法。我們爲了傳遞和接受雙字節的字符,在C++ 裏面需要使用【wchar_t】類型,這個函數導出的時候格式是以【extern "C"】C語言的格式爲標準的。
            到現在,我們可以直接運行【Example_16_1_2】項目的 exe 程序,(說明:調用協定是CallingConvention.Cdecl,纔可以調用成功,CallingConvention.ThisCall是舉例調用協定不一致出現問題,大家要熟悉),我們看看運行結果,效果如圖:
            

            現在,我們把調用協定修改爲【CallingConvention.FastCall】,在我測測試中,這些調用協定【CallingConvention.StdCall、CallingConvention.ThisCall、CallingConvention.Cdecl、CallingConvention.Winapi】都是正常執行的,所以,我只能換【CallingConvention.FastCall】,通過 Windbg 調試器查看一些運行結果。
            當把我們的項目加載到 Windebug 調試中直接運行,會拋出異常,和視頻中拋出的【訪問違例:Access violation】異常是不一樣的。

 1 0:000> g
 2 ModLoad: 00007ffd`15bf0000 00007ffd`15c9a000   C:\Windows\System32\ADVAPI32.dll
 3 ModLoad: 00007ffd`166f0000 00007ffd`1678e000   C:\Windows\System32\msvcrt.dll
 4 ModLoad: 00007ffd`168c0000 00007ffd`1695b000   C:\Windows\System32\sechost.dll
 5 ModLoad: 00007ffd`17550000 00007ffd`17673000   C:\Windows\System32\RPCRT4.dll
 6 ModLoad: 00007ffc`fd320000 00007ffc`fd3ca000   C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscoreei.dll
 7 ModLoad: 00007ffd`16960000 00007ffd`169b5000   C:\Windows\System32\SHLWAPI.dll
 8 ModLoad: 00007ffd`152c0000 00007ffd`152d3000   C:\Windows\System32\kernel.appcore.dll
 9 ModLoad: 00007ffd`14c80000 00007ffd`14c8a000   C:\Windows\SYSTEM32\VERSION.dll
10 ModLoad: 00007ffc`fbfa0000 00007ffc`fca62000   C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
11 ModLoad: 00007ffd`17320000 00007ffd`174c0000   C:\Windows\System32\USER32.dll
12 ModLoad: 00007ffd`15240000 00007ffd`15262000   C:\Windows\System32\win32u.dll
13 ModLoad: 00007ffc`fba00000 00007ffc`fbabd000   C:\Windows\SYSTEM32\ucrtbase_clr0400.dll
14 ModLoad: 00007ffc`fcd00000 00007ffc`fcd16000   C:\Windows\SYSTEM32\VCRUNTIME140_CLR0400.dll
15 ModLoad: 00007ffd`15bb0000 00007ffd`15bda000   C:\Windows\System32\GDI32.dll
16 ModLoad: 00007ffd`153b0000 00007ffd`154ba000   C:\Windows\System32\gdi32full.dll
17 ModLoad: 00007ffd`15310000 00007ffd`153ad000   C:\Windows\System32\msvcp_win.dll
18 ModLoad: 00007ffd`154c0000 00007ffd`155c0000   C:\Windows\System32\ucrtbase.dll
19 ModLoad: 00007ffd`16650000 00007ffd`16680000   C:\Windows\System32\IMM32.DLL
20 ModLoad: 00007ffd`17970000 00007ffd`17cc4000   C:\Windows\System32\combase.dll
21 (3cf8.225c): Unknown exception - code 04242420 (first chance)
22 ModLoad: 00007ffc`f3650000 00007ffc`f4c50000   C:\Windows\assembly\NativeImages_v4.0.30319_64\mscorlib\....\mscorlib.ni.dll
23 ModLoad: 00007ffd`16790000 00007ffd`168b9000   C:\Windows\System32\ole32.dll
24 ModLoad: 00007ffd`17970000 00007ffd`17cc4000   C:\Windows\System32\combase.dll
25 ModLoad: 00007ffd`15b30000 00007ffd`15baf000   C:\Windows\System32\bcryptPrimitives.dll
26 ModLoad: 00007ffc`f2c50000 00007ffc`f2d9f000   C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clrjit.dll
27 (3cf8.225c): C++ EH exception - code e06d7363 (first chance)
28 ModLoad: 0000017d`c7a10000 0000017d`c7b0a000   image0000017d`c7a10000
29 ModLoad: 0000017d`c7b10000 0000017d`c7c0a000   image0000017d`c7b10000
30 (3cf8.225c): CLR exception - code e0434352 (first chance)
31 ModLoad: 00007ffc`a83f0000 00007ffc`a855a000   C:\Windows\Microsoft.NET\Framework64\v4.0.30319\diasymreader.dll
32 ModLoad: 00007ffc`f1fe0000 00007ffc`f2c50000   C:\Windows\assembly\NativeImages_v4.0.30319_64\System\...\System.ni.dll
33 ModLoad: 00007ffc`f14b0000 00007ffc`f1f25000   C:\Windows\assembly\NativeImages_v4.0.30319_64\System.Core\...\System.Core.ni.dll
34 ModLoad: 00007ffd`14a40000 00007ffd`14a58000   C:\Windows\SYSTEM32\CRYPTSP.dll
35 ModLoad: 00007ffd`141e0000 00007ffd`14214000   C:\Windows\system32\rsaenh.dll
36 ModLoad: 00007ffd`152e0000 00007ffd`15307000   C:\Windows\System32\bcrypt.dll
37 ModLoad: 00007ffd`14a60000 00007ffd`14a6c000   C:\Windows\SYSTEM32\CRYPTBASE.dll
38 (3cf8.225c): CLR exception - code e0434352 (!!! second chance !!!)
39 KERNELBASE!RaiseException+0x69:
40 00007ffd`156d3e49 0f1f440000      nop     dword ptr [rax+rax]

            當然,我們直接運行程序,拋出的異常會更加直接。效果如圖:
            

            所以說,我們可以直接看程序拋出的異常,更能說明直接的問題,使用 Windebug 有點多此一舉。再次強調一下:我的結果和視頻的結果是不一樣的,原因未知。

            當然,雖然出錯了,我們也可以看看當前的調用棧。

 1 0:000> !clrstack
 2 OS Thread Id: 0x225c (0)
 3         Child SP               IP Call Site
 4 00000034903fe910 00007ffd156d3e49 [PrestubMethodFrame: 00000034903fe910] Example_16_1_2.Program.Alloc(System.String)
 5 00000034903febd0 00007ffc9ca708d1 Example_16_1_2.Program.Main(System.String[]) [E:\Visual Studio 2022\...\Example_16_1_2\Program.cs @ 17]
 6 00000034903fedf8 00007ffcfbfa6913 [GCFrame: 00000034903fedf8] 
 7 
 8 0:000> dp 00000034903fe910 l1
 9 00000034`903fe910  00007ffc`fc7711c0
10 0:000> ln 00007ffc`fc7711c0
11 Browse module
12 Set bu breakpoint
13 
14 (00007ffc`fc7711c0)   clr!PrestubMethodFrame::`vftable'   |  (00007ffc`fc771260)   clr!ExternalMethodFrame::`vftable'
15 Exact matches:
16 
17 0:000> u 00007ffc`fc7711c0
18 clr!PrestubMethodFrame::`vftable':
19 00007ffc`fc7711c0 70b6            jo      clr!FaultingExceptionFrame::`vftable'+0x50 (00007ffc`fc771178)
20 00007ffc`fc7711c2 0ffcfc          paddb   mm7,mm4
21 00007ffc`fc7711c5 7f00            jg      clr!PrestubMethodFrame::`vftable'+0x7 (00007ffc`fc7711c7)
22 00007ffc`fc7711c7 004007          add     byte ptr [rax+7],al
23 00007ffc`fc7711ca fb              sti
24 00007ffc`fc7711cb fb              sti
25 00007ffc`fc7711cc fc              cld
26 00007ffc`fc7711cd 7f00            jg      clr!PrestubMethodFrame::`vftable'+0xf (00007ffc`fc7711cf)


        2.3、委託異步引發的崩潰。
            調試源碼:Example_16_1_4 和 Example_16_1_5(C++)
            我們編譯我們的兩個項目,直接 ctrol+f5 運行 Example_16_1_4 項目,我們先看運行正常的情況,如果項正常運行,這個行代碼【GC.Collect();】需要註釋掉。運行結果如圖:
            
            這是正常的情況,接下來,我們取消對【GC.Collect();】這行代碼的註釋,就是可以執行垃圾回收。我們重新編譯項目,ctrol+f5運行項目,執行效果如圖:
            

            在這裏,我需要說明一下,我的演示結果和【一線碼農】的視頻演示的結果是不一樣的,他的系統也崩潰了,提示的錯誤消息是【未經處理的異常:System.AccessviolationException:嘗試讀取或者寫入受保護的內存,這通常指示其他內存已損壞】。這個問題我還沒搞清楚,如果有知道的可以告訴我。

            上面是運行程序出現的問題,接下來,我們使用 Windbg 查找一下問題。
            我們編譯項目 Example_16_1_4,打開 Windbg,點擊【文件】----》【launch executable】附加程序,打開調試器的界面,程序已經處於中斷狀態。我本來想使用【bp Example_16_1_4!AsyncProcess】命令給【AsyncProcess】方法下斷點,但是執行不成功。

1 0:000> bp Example_16_1_4!AsyncProcess
2 Couldn't resolve error at 'Example_16_1_4!AsyncProcess'

            那我們就通過源碼的方式直接給 C++ AsyncProcess 方法下斷點。我們點擊 Windbg 菜單欄,依次選擇【Source】--->【Open Source File】,打開選擇我們的 C++ 項目中的 Example_16_1_5.cpp 文件。效果如圖:
            

            斷點設置完成後,我們直接執行【g】命令,繼續運行調試器。效果如圖:
            

            我們繼續執行【dv】命令,可以看到有一個 ptr,那就是我們從託管代碼中傳遞到非託管代碼中的委託,就是一個指針。

1 0:000> dv
2             ptr = 0x000001cc`459a090c
3         hThread = 0x00007ff8`5aa40f58

            我們可以使用【u 1cc459a090c】命令,查看一下這個 ptr 是什麼。

1 0:000> u 1cc459a090c
2 000001cc`459a090c 49bae0089a45cc010000 mov r10,1CC459A08E0h
3 000001cc`459a0916 48b8c021275af87f0000 mov rax,offset clr!UMThunkStub (00007ff8`5a2721c0)
4 000001cc`459a0920 48ffe0          jmp     rax
5 000001cc`459a0923 0000            add     byte ptr [rax],al
6 000001cc`459a0925 0000            add     byte ptr [rax],al
7 000001cc`459a0927 00ababababab    add     byte ptr [rbx-54545455h],ch
8 000001cc`459a092d ab              stos    dword ptr [rdi]
9 000001cc`459a092e ab              stos    dword ptr [rdi]

            我們在【PCallback callback = (PCallback)lpParameter;】這行代碼在下一個斷點,也就是2秒後會執行這個回調。效果如圖:
            

            斷點設置成功後,我們繼續執行調試器,使用【g】命令。

1 0:000> g
2 Breakpoint 1 hit
3 Example_16_1_5!ThreadWorkItem+0x3e:
4 00007fff`d444172e 488b8500010000  mov     rax,qword ptr [rbp+100h] ss:0000000a`735ffb60=000001cc459a090c

            我們繼續執行,會在我們設置斷點的地方成功斷住。效果如圖:
            

            到了這裏,我們在使用【u 1cc459a090c】命令,查看一下這個 ptr 是什麼東西。

1 0:007> u 1cc459a090c
2 000001cc`459a090c ee              out     dx,al
3 000001cc`459a090d fe              ???
4 000001cc`459a090e ee              out     dx,al
5 000001cc`459a090f fe              ???
6 000001cc`459a0910 ee              out     dx,al
7 000001cc`459a0911 fe              ???
8 000001cc`459a0912 ee              out     dx,al
9 000001cc`459a0913 fe              ???

            都是亂碼了,都是 ??? 問號了,就是說 ptr 不存在了。說明已經被我們 GC 回收了。我們也可以使用【dv】命令查看一下變化。

1 0:007> dv
2     lpParameter = 0x000001cc`459a090c
3        callback = 0x00000000`00000000

            callback 是空值了。
            如果遇到這樣的情況,我們怎麼解決呢?其實很簡單,在我們的 C# 代碼中,聲明一個靜態的 handle 就可以了,如:static GCHandle handle;在我的代碼中,註釋的部分就是解決辦法。

        2.4、非託管內存泄露
            調試源碼:Example_16_1_6 和 Example_16_1_7(C++)項目
            在C++ 項目中,如果我們聲明瞭【數組】,是需要自己釋放的,如果忘記釋放,內存就會暴漲了。我們直接運行項目【Example_16_1_6】,看一下效果:
            

            大家可以試試,內存漲得很快。
            這次我們是通過 dump 文件進行分析的,生成 dump 文件有兩種方式,第一種是通過【任務管理器】來生成的。第二種是通過【ProcessExplorer】工具來生成。

            第一種:我們首先運行我們的項目 Example_16_1_6.exe,然後,我們打開【任務管理器】,找到我們的項目進程,我的進程名是【Example_16_1_6】,如果左側有箭頭,點擊打開摺疊的內容,在項目地址名字上點擊右鍵,選擇保存【創建轉出文件】,保存成功,會彈出提示框文件的位置,效果如下:
            

            彈出保存數據對話框,保存對話框運行時間的長短是有你保存的數據多少決定的。如圖:
            

            這個保存的過程,和你的程序運行時間的長短有關係。保存成功,如圖:
            

            我們的 dump 文件如圖:

            

            第二種:我們使用【ProcessExplorer】工具抓 dump 文件,個人感覺這個更好的,抓的文件更好用、更可靠。
            首先運行我們的項目 Example_16_1_6.exe,然後打開【ProcessExplorer】工具,然後,在右側的【Filter by name】過濾進程,輸入我們的進程名稱,比如:Example_16,不用輸入全名,當然輸入全名也可以。如圖:
             

            我們找到了我們的項目進程,在項目上點擊右鍵,依次選擇【Create Dump】----》【Create MiniDump】或者【Create Full Dump】,我選擇的是【Create Full Dump】創建完整的 dump 文件,選擇保存的文件路徑就可以了。
            在開始之前,我們需要做一些準備工作,否則,調試結果有些數據是看不到的,我第一次就是這樣的,原來是漏了步驟了,切記,切記。我們必須打開【棧追蹤】。我已經安裝了 【Windows Kits】,如果沒有安裝的,就請去微軟官網下載安裝一下,畢竟 gflags.exe 包含在這個集合中。
            Windows Kits 官網下載地址:https://learn.microsoft.com/zh-cn/windows-hardware/drivers/download-the-wdk
            我的安裝目錄在:D:\Windows Kits\10\Debuggers ,大家根據自己的情況去查找。爲了避免每次都進入安裝目錄,最好把 gflags.exe 的安裝目錄配置到【環境變量】裏面,使用就方便了。針對我們的項目執行一下命令:gflags /i Example_16_1_6.exe +ust 。效果如圖:
            


            有了  Dump 文件就容易了,我們就可以使用 Windbg 調試了。我們打開 Windbg,點擊【文件】----》【Open dump file】打開我們的 Dump 文件,打開調試器的界面,程序已經處於中斷狀態。我們先看看託管堆的情況,執行命令【!heap -s】。

 1 0:000> !heap -s
 2 
 3 
 4 ************************************************************************************************************************
 5                                               NT HEAP STATS BELOW
 6 ************************************************************************************************************************
 7 NtGlobalFlag enables following debugging aids for new heaps:
 8     stack back traces(必須開啓棧跟蹤,否則後面的操作有些不能輸出)
 9 LFH Key                   : 0xb1c3e0529717db20
10 Termination on corruption : ENABLED
11           Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
12                             (k)     (k)    (k)     (k) length      blocks cont. heap 
13 -------------------------------------------------------------------------------------
14 000001f3651e0000 08000002 3869212 3843092 3869108  58051   283   243    1      3   LFH
15 000001f363950000 08008000      64      4     64      2     1     1    0      0      
16 000001f3655b0000 08001002     164     36     60      5     2     1    0      0   LFH
17 000001f365420000 08001002     164     36     60      4     2     1    0      0   LFH
18 000001f366df0000 08001002      60      8     60      2     1     1    0      0      
19 000001f366f70000 08041002      60      8     60      5     1     1    0      0      
20 000001f37f8b0000 08041002      60      8     60      2     1     1    0      0      
21 -------------------------------------------------------------------------------------
          我們使用【!heap -h 000001f3651e0000】命令查看一下句柄,發現內容太多了,我就不一一展示了。
  1 0:000> !heap -h 000001f3651e0000
  2 HEAPEXT: Unable to get address of ntdll!RtlpHeapInvalidBadAddress.
  3 Index   Address  Name      Debugging options enabled
  4   1:   1f3651e0000 
  5     Segment at 000001f3651e0000 to 000001f3652df000 (000ff000 bytes committed)
  6     Segment at 000001f37f300000 to 000001f37f3ff000 (000e7000 bytes committed)
  7     Segment at 000001f37f8c0000 to 000001f37fabf000 (001d6000 bytes committed)
  8     Segment at 000001f37fac0000 to 000001f37febf000 (003ee000 bytes committed)
  9     Segment at 000001f300000000 to 000001f3007ff000 (007db000 bytes committed)
 10     Segment at 000001f300800000 to 000001f3017cf000 (00fb5000 bytes committed)
 11     Segment at 000001f3017d0000 to 000001f30279f000 (00fb5000 bytes committed)
 12     Segment at 000001f3027a0000 to 000001f30376f000 (00fb5000 bytes committed)
 13     Segment at 000001f303770000 to 000001f30473f000 (00fb5000 bytes committed)
 14     Segment at 000001f304740000 to 000001f30570f000 (00fb5000 bytes committed)
 15     Segment at 000001f305710000 to 000001f3066df000 (00fb5000 bytes committed)
 16     Segment at 000001f3066e0000 to 000001f3076af000 (00fb5000 bytes committed)
 17     Segment at 000001f3076b0000 to 000001f30867f000 (00fb5000 bytes committed)
 18     Segment at 000001f308680000 to 000001f30964f000 (00fb5000 bytes committed)
 19     Segment at 000001f309650000 to 000001f30a61f000 (00fb5000 bytes committed)
 20     Segment at 000001f30a620000 to 000001f30b5ef000 (00fb5000 bytes committed)
 21     Segment at 000001f30b5f0000 to 000001f30c5bf000 (00fb5000 bytes committed)
 22     Segment at 000001f30c5c0000 to 000001f30d58f000 (00fb5000 bytes committed)
 23     Segment at 000001f30d590000 to 000001f30e55f000 (00fb5000 bytes committed)
 24     Segment at 000001f30e560000 to 000001f30f52f000 (00fb5000 bytes committed)
 25     Segment at 000001f30f530000 to 000001f3104ff000 (00fb5000 bytes committed)
 26     Segment at 000001f310500000 to 000001f3114cf000 (00fb5000 bytes committed)
 27     Segment at 000001f3114d0000 to 000001f31249f000 (00fb5000 bytes committed)
 28     Segment at 000001f3124a0000 to 000001f31346f000 (00fb5000 bytes committed)
 29     Segment at 000001f313470000 to 000001f31443f000 (00fb5000 bytes committed)
 30     Segment at 000001f314440000 to 000001f31540f000 (00fb5000 bytes committed)
 31     Segment at 000001f315410000 to 000001f3163df000 (00fb5000 bytes committed)
 32     Segment at 000001f3163e0000 to 000001f3173af000 (00fb5000 bytes committed)
 33     Segment at 000001f3173b0000 to 000001f31837f000 (00fb5000 bytes committed)
 34     Segment at 000001f318380000 to 000001f31934f000 (00fb5000 bytes committed)
 35     Segment at 000001f319350000 to 000001f31a31f000 (00fb5000 bytes committed)
 36     Segment at 000001f31a320000 to 000001f31b2ef000 (00fb5000 bytes committed)
 37     Segment at 000001f31b2f0000 to 000001f31c2bf000 (00fb5000 bytes committed)
 38     Segment at 000001f31c2c0000 to 000001f31d28f000 (00fb5000 bytes committed)
 39     Segment at 000001f31d290000 to 000001f31e25f000 (00fb5000 bytes committed)
 40     Segment at 000001f31e260000 to 000001f31f22f000 (00fb5000 bytes committed)
 41     Segment at 000001f31f230000 to 000001f3201ff000 (00fb5000 bytes committed)
 42     Segment at 000001f320200000 to 000001f3211cf000 (00fb5000 bytes committed)
 43     Segment at 000001f3211d0000 to 000001f32219f000 (00fb5000 bytes committed)
 44     Segment at 000001f3221a0000 to 000001f32316f000 (00fb5000 bytes committed)
 45     Segment at 000001f323170000 to 000001f32413f000 (00fb5000 bytes committed)
 46     Segment at 000001f324140000 to 000001f32510f000 (00fb5000 bytes committed)
 47     Segment at 000001f325110000 to 000001f3260df000 (00fb5000 bytes committed)
 48     Segment at 000001f3260e0000 to 000001f3270af000 (00fb5000 bytes committed)
 49     Segment at 000001f3270b0000 to 000001f32807f000 (00fb5000 bytes committed)
 50     Segment at 000001f328080000 to 000001f32904f000 (00fb5000 bytes committed)
 51     Segment at 000001f329050000 to 000001f32a01f000 (00fb5000 bytes committed)
 52     Segment at 000001f32a020000 to 000001f32afef000 (00fb5000 bytes committed)
 53     Segment at 000001f32aff0000 to 000001f32bfbf000 (00fb5000 bytes committed)
 54     Segment at 000001f32bfc0000 to 000001f32cf8f000 (00fb5000 bytes committed)
 55     Segment at 000001f32cf90000 to 000001f32df5f000 (00fb5000 bytes committed)
 56     Segment at 000001f32df60000 to 000001f32ef2f000 (00fb5000 bytes committed)
 57     Segment at 000001f32ef30000 to 000001f32feff000 (00fb5000 bytes committed)
 58     Segment at 000001f32ff00000 to 000001f330ecf000 (00fb5000 bytes committed)
 59     Segment at 000001f330ed0000 to 000001f331e9f000 (00fb5000 bytes committed)
 60     Segment at 000001f331ea0000 to 000001f332e6f000 (00fb5000 bytes committed)
 61     Segment at 000001f332e70000 to 000001f333e3f000 (00fb5000 bytes committed)
 62     Segment at 000001f333e40000 to 000001f334e0f000 (00fb5000 bytes committed)
 63     Segment at 000001f334e10000 to 000001f335ddf000 (00fb5000 bytes committed)
 64     Segment at 000001f335de0000 to 000001f336daf000 (00fb5000 bytes committed)
 65     Segment at 000001f336db0000 to 000001f337d7f000 (00fb5000 bytes committed)
 66     Segment at 000001f337d80000 to 000001f338d4f000 (00fb5000 bytes committed)
 67     Segment at 000001f338d50000 to 000001f339d1f000 (00fb5000 bytes committed)
 68     Segment at 000001f339d20000 to 000001f33acef000 (00fb5000 bytes committed)
 69     Segment at 000001f33acf0000 to 000001f33bcbf000 (00fb5000 bytes committed)
 70     Segment at 000001f33bcc0000 to 000001f33cc8f000 (00fb5000 bytes committed)
 71     Segment at 000001f33cc90000 to 000001f33dc5f000 (00fb5000 bytes committed)
 72     Segment at 000001f33dc60000 to 000001f33ec2f000 (00fb5000 bytes committed)
 73     Segment at 000001f33ec30000 to 000001f33fbff000 (00fb5000 bytes committed)
 74     Segment at 000001f33fc00000 to 000001f340bcf000 (00fb5000 bytes committed)
 75     Segment at 000001f340bd0000 to 000001f341b9f000 (00fb5000 bytes committed)
 76     Segment at 000001f341ba0000 to 000001f342b6f000 (00fb5000 bytes committed)
 77     Segment at 000001f342b70000 to 000001f343b3f000 (00fb5000 bytes committed)
 78     Segment at 000001f343b40000 to 000001f344b0f000 (00fb5000 bytes committed)
 79     Segment at 000001f344b10000 to 000001f345adf000 (00fb5000 bytes committed)
 80     Segment at 000001f345ae0000 to 000001f346aaf000 (00fb5000 bytes committed)
 81     Segment at 000001f346ab0000 to 000001f347a7f000 (00fb5000 bytes committed)
 82     Segment at 000001f347a80000 to 000001f348a4f000 (00fb5000 bytes committed)
 83     Segment at 000001f348a50000 to 000001f349a1f000 (00fb5000 bytes committed)
 84     Segment at 000001f349a20000 to 000001f34a9ef000 (00fb5000 bytes committed)
 85     Segment at 000001f34a9f0000 to 000001f34b9bf000 (00fb5000 bytes committed)
 86     Segment at 000001f34b9c0000 to 000001f34c98f000 (00fb5000 bytes committed)
 87     Segment at 000001f34c990000 to 000001f34d95f000 (00fb5000 bytes committed)
 88     Segment at 000001f34d960000 to 000001f34e92f000 (00fb5000 bytes committed)
 89     Segment at 000001f34e930000 to 000001f34f8ff000 (00fb5000 bytes committed)
 90     Segment at 000001f34f900000 to 000001f3508cf000 (00fb5000 bytes committed)
 91     Segment at 000001f3508d0000 to 000001f35189f000 (00fb5000 bytes committed)
 92     Segment at 000001f3518a0000 to 000001f35286f000 (00fb5000 bytes committed)
 93     Segment at 000001f352870000 to 000001f35383f000 (00fb5000 bytes committed)
 94     Segment at 000001f353840000 to 000001f35480f000 (00fb5000 bytes committed)
 95     Segment at 000001f354810000 to 000001f3557df000 (00fb5000 bytes committed)
 96     Segment at 000001f3557e0000 to 000001f3567af000 (00fb5000 bytes committed)
 97     Segment at 000001f3567b0000 to 000001f35777f000 (00fb5000 bytes committed)
 98     Segment at 000001f357780000 to 000001f35874f000 (00fb5000 bytes committed)
 99     Segment at 000001f358750000 to 000001f35971f000 (00fb5000 bytes committed)
100     Segment at 000001f359720000 to 000001f35a6ef000 (00fb5000 bytes committed)
101     Segment at 000001f35a6f0000 to 000001f35b6bf000 (00fb5000 bytes committed)
102     Segment at 000001f35b6c0000 to 000001f35c68f000 (00fb5000 bytes committed)
103     Segment at 000001f35c690000 to 000001f35d65f000 (00fb5000 bytes committed)
104     Segment at 000001f35d660000 to 000001f35e62f000 (00fb5000 bytes committed)
105     Segment at 000001f35e630000 to 000001f35f5ff000 (00fb5000 bytes committed)
106     Segment at 000001f35f600000 to 000001f3605cf000 (00fb5000 bytes committed)
107     Segment at 000001f3605d0000 to 000001f36159f000 (00fb5000 bytes committed)
108     Segment at 000001f3615a0000 to 000001f36256f000 (00fb5000 bytes committed)
109     Segment at 000001f362570000 to 000001f36353f000 (00fb5000 bytes committed)
110     Segment at 000001f37fec0000 to 000001f380e8f000 (00fb5000 bytes committed)
111     Segment at 000001f380e90000 to 000001f381e5f000 (00fb5000 bytes committed)
112     Segment at 000001f381e60000 to 000001f382e2f000 (00fb5000 bytes committed)
113     Segment at 000001f382e30000 to 000001f383dff000 (00fb5000 bytes committed)
114     Segment at 000001f383e00000 to 000001f384dcf000 (00fb5000 bytes committed)
115     Segment at 000001f384dd0000 to 000001f385d9f000 (00fb5000 bytes committed)
116     Segment at 000001f385da0000 to 000001f386d6f000 (00fb5000 bytes committed)
117     Segment at 000001f386d70000 to 000001f387d3f000 (00fb5000 bytes committed)
118     Segment at 000001f387d40000 to 000001f388d0f000 (00fb5000 bytes committed)
119     Segment at 000001f388d10000 to 000001f389cdf000 (00fb5000 bytes committed)
120     Segment at 000001f389ce0000 to 000001f38acaf000 (00fb5000 bytes committed)
121     Segment at 000001f38acb0000 to 000001f38bc7f000 (00fb5000 bytes committed)
122     Segment at 000001f38bc80000 to 000001f38cc4f000 (00fb5000 bytes committed)
123     Segment at 000001f38cc50000 to 000001f38dc1f000 (00fb5000 bytes committed)
124     Segment at 000001f38dc20000 to 000001f38ebef000 (00fb5000 bytes committed)
125     Segment at 000001f38ebf0000 to 000001f38fbbf000 (00fb5000 bytes committed)
126     Segment at 000001f38fbc0000 to 000001f390b8f000 (00fb5000 bytes committed)
127     Segment at 000001f390b90000 to 000001f391b5f000 (00fb5000 bytes committed)
128     Segment at 000001f391b60000 to 000001f392b2f000 (00fb5000 bytes committed)
129     Segment at 000001f392b30000 to 000001f393aff000 (00fb5000 bytes committed)
130     Segment at 000001f393b00000 to 000001f394acf000 (00fb5000 bytes committed)
131     Segment at 000001f394ad0000 to 000001f395a9f000 (00fb5000 bytes committed)
132     Segment at 000001f395aa0000 to 000001f396a6f000 (00fb5000 bytes committed)
133     Segment at 000001f396a70000 to 000001f397a3f000 (00fb5000 bytes committed)
134     Segment at 000001f397a40000 to 000001f398a0f000 (00fb5000 bytes committed)
135     Segment at 000001f398a10000 to 000001f3999df000 (00fb5000 bytes committed)
136     Segment at 000001f3999e0000 to 000001f39a9af000 (00fb5000 bytes committed)
137     Segment at 000001f39a9b0000 to 000001f39b97f000 (00fb5000 bytes committed)
138     Segment at 000001f39b980000 to 000001f39c94f000 (00fb5000 bytes committed)
139     Segment at 000001f39c950000 to 000001f39d91f000 (00fb5000 bytes committed)
140     Segment at 000001f39d920000 to 000001f39e8ef000 (00fb5000 bytes committed)
141     Segment at 000001f39e8f0000 to 000001f39f8bf000 (00fb5000 bytes committed)
142     Segment at 000001f39f8c0000 to 000001f3a088f000 (00fb5000 bytes committed)
143     Segment at 000001f3a0890000 to 000001f3a185f000 (00fb5000 bytes committed)
144     Segment at 000001f3a1860000 to 000001f3a282f000 (00fb5000 bytes committed)
145     Segment at 000001f3a2830000 to 000001f3a37ff000 (00fb5000 bytes committed)
146     Segment at 000001f3a3800000 to 000001f3a47cf000 (00fb5000 bytes committed)
147     Segment at 000001f3a47d0000 to 000001f3a579f000 (00fb5000 bytes committed)
148     Segment at 000001f3a57a0000 to 000001f3a676f000 (00fb5000 bytes committed)
149     Segment at 000001f3a6770000 to 000001f3a773f000 (00fb5000 bytes committed)
150     Segment at 000001f3a7740000 to 000001f3a870f000 (00fb5000 bytes committed)
151     Segment at 000001f3a8710000 to 000001f3a96df000 (00fb5000 bytes committed)
152     Segment at 000001f3a96e0000 to 000001f3aa6af000 (00fb5000 bytes committed)
153     Segment at 000001f3aa6b0000 to 000001f3ab67f000 (00fb5000 bytes committed)
154     Segment at 000001f3ab680000 to 000001f3ac64f000 (00fb5000 bytes committed)
155     Segment at 000001f3ac650000 to 000001f3ad61f000 (00fb5000 bytes committed)
156     Segment at 000001f3ad620000 to 000001f3ae5ef000 (00fb5000 bytes committed)
157     Segment at 000001f3ae5f0000 to 000001f3af5bf000 (00fb5000 bytes committed)
158     Segment at 000001f3af5c0000 to 000001f3b058f000 (00fb5000 bytes committed)
159     Segment at 000001f3b0590000 to 000001f3b155f000 (00fb5000 bytes committed)
160     Segment at 000001f3b1560000 to 000001f3b252f000 (00fb5000 bytes committed)
161     Segment at 000001f3b2530000 to 000001f3b34ff000 (00fb5000 bytes committed)
162     Segment at 000001f3b3500000 to 000001f3b44cf000 (00fb5000 bytes committed)
163     Segment at 000001f3b44d0000 to 000001f3b549f000 (00fb5000 bytes committed)
164     Segment at 000001f3b54a0000 to 000001f3b646f000 (00fb5000 bytes committed)
165     Segment at 000001f3b6470000 to 000001f3b743f000 (00fb5000 bytes committed)
166     Segment at 000001f3b7440000 to 000001f3b840f000 (00fb5000 bytes committed)
167     Segment at 000001f3b8410000 to 000001f3b93df000 (00fb5000 bytes committed)
168     Segment at 000001f3b93e0000 to 000001f3ba3af000 (00fb5000 bytes committed)
169     Segment at 000001f3ba3b0000 to 000001f3bb37f000 (00fb5000 bytes committed)
170     Segment at 000001f3bb380000 to 000001f3bc34f000 (00fb5000 bytes committed)
171     Segment at 000001f3bc350000 to 000001f3bd31f000 (00fb5000 bytes committed)
172     Segment at 000001f3bd320000 to 000001f3be2ef000 (00fb5000 bytes committed)
173     Segment at 000001f3be2f0000 to 000001f3bf2bf000 (00fb5000 bytes committed)
174     Segment at 000001f3bf2c0000 to 000001f3c028f000 (00fb5000 bytes committed)
175     Segment at 000001f3c0290000 to 000001f3c125f000 (00fb5000 bytes committed)
176     Segment at 000001f3c1260000 to 000001f3c222f000 (00fb5000 bytes committed)
177     Segment at 000001f3c2230000 to 000001f3c31ff000 (00fb5000 bytes committed)
178     Segment at 000001f3c3200000 to 000001f3c41cf000 (00fb5000 bytes committed)
179     Segment at 000001f3c41d0000 to 000001f3c519f000 (00fb5000 bytes committed)
180     Segment at 000001f3c51a0000 to 000001f3c616f000 (00fb5000 bytes committed)
181     Segment at 000001f3c6170000 to 000001f3c713f000 (00fb5000 bytes committed)
182     Segment at 000001f3c7140000 to 000001f3c810f000 (00fb5000 bytes committed)
183     Segment at 000001f3c8110000 to 000001f3c90df000 (00fb5000 bytes committed)
184     Segment at 000001f3c90e0000 to 000001f3ca0af000 (00fb5000 bytes committed)
185     Segment at 000001f3ca0b0000 to 000001f3cb07f000 (00fb5000 bytes committed)
186     Segment at 000001f3cb080000 to 000001f3cc04f000 (00fb5000 bytes committed)
187     Segment at 000001f3cc050000 to 000001f3cd01f000 (00fb5000 bytes committed)
188     Segment at 000001f3cd020000 to 000001f3cdfef000 (00fb5000 bytes committed)
189     Segment at 000001f3cdff0000 to 000001f3cefbf000 (00fb5000 bytes committed)
190     Segment at 000001f3cefc0000 to 000001f3cff8f000 (00fb5000 bytes committed)
191     Segment at 000001f3cff90000 to 000001f3d0f5f000 (00fb5000 bytes committed)
192     Segment at 000001f3d0f60000 to 000001f3d1f2f000 (00fb5000 bytes committed)
193     Segment at 000001f3d1f30000 to 000001f3d2eff000 (00fb5000 bytes committed)
194     Segment at 000001f3d2f00000 to 000001f3d3ecf000 (00fb5000 bytes committed)
195     Segment at 000001f3d3ed0000 to 000001f3d4e9f000 (00fb5000 bytes committed)
196     Segment at 000001f3d4ea0000 to 000001f3d5e6f000 (00fb5000 bytes committed)
197     Segment at 000001f3d5e70000 to 000001f3d6e3f000 (00fb5000 bytes committed)
198     Segment at 000001f3d6e40000 to 000001f3d7e0f000 (00fb5000 bytes committed)
199     Segment at 000001f3d7e10000 to 000001f3d8ddf000 (00fb5000 bytes committed)
200     Segment at 000001f3d8de0000 to 000001f3d9daf000 (00fb5000 bytes committed)
201     Segment at 000001f3d9db0000 to 000001f3dad7f000 (00fb5000 bytes committed)
202     Segment at 000001f3dad80000 to 000001f3dbd4f000 (00fb5000 bytes committed)
203     Segment at 000001f3dbd50000 to 000001f3dcd1f000 (00fb5000 bytes committed)
204     Segment at 000001f3dcd20000 to 000001f3ddcef000 (00fb5000 bytes committed)
205     Segment at 000001f3ddcf0000 to 000001f3decbf000 (00fb5000 bytes committed)
206     Segment at 000001f3decc0000 to 000001f3dfc8f000 (00fb5000 bytes committed)
207     Segment at 000001f3dfc90000 to 000001f3e0c5f000 (00fb5000 bytes committed)
208     Segment at 000001f3e0c60000 to 000001f3e1c2f000 (00fb5000 bytes committed)
209     Segment at 000001f3e1c30000 to 000001f3e2bff000 (00fb5000 bytes committed)
210     Segment at 000001f3e2c00000 to 000001f3e3bcf000 (00fb5000 bytes committed)
211     Segment at 000001f3e3bd0000 to 000001f3e4b9f000 (00fb5000 bytes committed)
212     Segment at 000001f3e4ba0000 to 000001f3e5b6f000 (00fb5000 bytes committed)
213     Segment at 000001f3e5b70000 to 000001f3e6b3f000 (00fb5000 bytes committed)
214     Segment at 000001f3e6b40000 to 000001f3e7b0f000 (00fb5000 bytes committed)
215     Segment at 000001f3e7b10000 to 000001f3e8adf000 (00fb5000 bytes committed)
216     Segment at 000001f3e8ae0000 to 000001f3e9aaf000 (00fb5000 bytes committed)
217     Segment at 000001f3e9ab0000 to 000001f3eaa7f000 (00fb5000 bytes committed)
218     Segment at 000001f3eaa80000 to 000001f3eba4f000 (00fb5000 bytes committed)
219     Segment at 000001f3eba50000 to 000001f3eca1f000 (00fb5000 bytes committed)
220     Segment at 000001f3eca20000 to 000001f3ed9ef000 (00fb5000 bytes committed)
221     Segment at 000001f3ed9f0000 to 000001f3ee9bf000 (00fb5000 bytes committed)
222     Segment at 000001f3ee9c0000 to 000001f3ef98f000 (00fb5000 bytes committed)
223     Segment at 000001f3ef990000 to 000001f3f095f000 (00fb5000 bytes committed)
224     Segment at 000001f3f0960000 to 000001f3f192f000 (00fb5000 bytes committed)
225     Segment at 000001f3f1930000 to 000001f3f28ff000 (00fb5000 bytes committed)
226     Segment at 000001f3f2900000 to 000001f3f38cf000 (00fb5000 bytes committed)
227     Segment at 000001f3f38d0000 to 000001f3f489f000 (00fb5000 bytes committed)
228     Segment at 000001f3f48a0000 to 000001f3f586f000 (00fb5000 bytes committed)
229     Segment at 000001f3f5870000 to 000001f3f683f000 (00fb5000 bytes committed)
230     Segment at 000001f3f6840000 to 000001f3f780f000 (00fb5000 bytes committed)
231     Segment at 000001f3f7810000 to 000001f3f87df000 (00fb5000 bytes committed)
232     Segment at 000001f3f87e0000 to 000001f3f97af000 (00fb5000 bytes committed)
233     Segment at 000001f3f97b0000 to 000001f3fa77f000 (00fb5000 bytes committed)
234     Segment at 000001f3fa780000 to 000001f3fb74f000 (00fb5000 bytes committed)
235     Segment at 000001f3fb750000 to 000001f3fc71f000 (00fb5000 bytes committed)
236     Segment at 000001f3fc720000 to 000001f3fd6ef000 (00fb5000 bytes committed)
237     Segment at 000001f3fd6f0000 to 000001f3fe6bf000 (00fb5000 bytes committed)
238     Segment at 000001f3fe6c0000 to 000001f3ff68f000 (00fb5000 bytes committed)
239     Segment at 000001f3ff690000 to 000001f40065f000 (00fb5000 bytes committed)
240     Segment at 000001f400660000 to 000001f40162f000 (00fb5000 bytes committed)
241     Segment at 000001f401630000 to 000001f4025ff000 (00fb5000 bytes committed)
242     Segment at 000001f402600000 to 000001f4035cf000 (00fb5000 bytes committed)
243     Segment at 000001f4035d0000 to 000001f40459f000 (00fb5000 bytes committed)
244     Segment at 000001f4045a0000 to 000001f40556f000 (00fb5000 bytes committed)
245     Segment at 000001f405570000 to 000001f40653f000 (00fb5000 bytes committed)
246     Segment at 000001f406540000 to 000001f40750f000 (00fb5000 bytes committed)
247     Segment at 000001f407510000 to 000001f4084df000 (00eec000 bytes committed)
248     Flags:                08000002
249     ForceFlags:           00000000
250     Granularity:          16 bytes
251     Segment Reserve:      ec360000
252     Segment Commit:       00002000
253     DeCommit Block Thres: 00000400
254     DeCommit Total Thres: 00001000
255     Total Free Size:      0038b0df
256     Max. Allocation Size: 00007ffffffdefff
257     Lock Variable at:     000001f3651e02c0
258     Next TagIndex:        0000
259     Maximum TagIndex:     0000
260     Tag Entries:          00000000
261     PsuedoTag Entries:    00000000
262     Virtual Alloc List:   1f3651e0110
263         000001f366e09000: 00100000 [commited 101000, unused 1000] - busy (b)
264     Uncommitted ranges:   1f3651e00f0
265     FreeList[ 00 ] at 000001f3651e0150: 000001f301778010 . 000001f37f33fe80   (283 blocks)
266 
267     Heap entries for Segment00 in Heap 000001f3651e0000
268                  address: psize . size  flags   state (requested size)
269         000001f3651e0000: 00000 . 00740 [101] - busy (73f)
270         000001f3651e0740: 00740 . 00080 [101] - busy (50)
271         000001f3651e07c0: 00080 . 00060 [101] - busy (30)
272         000001f3651e0820: 00060 . 00030 [101] - busy (4)
273         000001f3651e0850: 00030 . 00130 [101] - busy (100)
274         000001f3651e0980: 00130 . 00200 [101] - busy (1d8)
275         000001f3651e0b80: 00200 . 00200 [101] - busy (1d8)
276         000001f3651e0d80: 00200 . 00070 [101] - busy (48)
277         000001f3651e0df0: 00070 . 00030 [101] - busy (4)
278         000001f3651e0e20: 00030 . 00040 [101] - busy (10)
279         000001f3651e0e60: 00040 . 00130 [101] - busy (100)
280         000001f3651e0f90: 00130 . 00130 [101] - busy (100)
281         000001f3651e10c0: 00130 . 01510 [101] - busy (14e8)
282         000001f3651e25d0: 01510 . 00950 [101] - busy (91c)
283         000001f3651e2f20: 00950 . 00070 [101] - busy (3c)
284         000001f3651e2f90: 00070 . 00060 [101] - busy (30)
285         000001f3651e2ff0: 00060 . 00090 [101] - busy (62)
286         000001f3651e3080: 00090 . 00150 [101] - busy (120)
287         000001f3651e31d0: 00150 . 00080 [101] - busy (50)
288         000001f3651e3250: 00080 . 00150 [101] - busy (120)
289         000001f3651e33a0: 00150 . 00080 [101] - busy (50)
290         000001f3651e3420: 00080 . 00260 [101] - busy (238)
291         000001f3651e3680: 00260 . 00060 [101] - busy (30)
292         000001f3651e36e0: 00060 . 00090 [101] - busy (68)
293         000001f3651e3770: 00090 . 00040 [101] - busy (10)
294         000001f3651e37b0: 00040 . 00150 [101] - busy (120)
295         000001f3651e3900: 00150 . 00080 [101] - busy (50)
296         000001f3651e3980: 00080 . 00070 [101] - busy (40)
297         000001f3651e39f0: 00070 . 00030 [101] - busy (8)
298         000001f3651e3a20: 00030 . 00050 [101] - busy (20)
299         000001f3651e3a70: 00050 . 00080 [101] - busy (50)
300         000001f3651e3af0: 00080 . 00090 [101] - busy (68)
301         000001f3651e3b80: 00090 . 00150 [101] - busy (120)
302         000001f3651e3cd0: 00150 . 00080 [101] - busy (50)
303         000001f3651e3d50: 00080 . 00070 [101] - busy (42)
304         000001f3651e3dc0: 00070 . 00130 [101] - busy (100)
305         000001f3651e3ef0: 00130 . 00130 [101] - busy (100)
306         000001f3651e4020: 00130 . 00060 [101] - busy (30)
307         000001f3651e4080: 00060 . 00070 [101] - busy (30)
308         000001f3651e40f0: 00070 . 00050 [101] - busy (20)
309         000001f3651e4140: 00050 . 00070 [101] - busy (42)
310         000001f3651e41b0: 00070 . 000a0 [101] - busy (75)
311         000001f3651e4250: 000a0 . 00150 [101] - busy (120)
312         000001f3651e43a0: 00150 . 00080 [101] - busy (50)
313         000001f3651e4420: 00080 . 00070 [101] - busy (46)
314         000001f3651e4490: 00070 . 00430 [101] - busy (400)
315         000001f3651e48c0: 00430 . 00430 [101] - busy (400)
316         000001f3651e4cf0: 00430 . 00130 [101] - busy (100)
317         000001f3651e4e20: 00130 . 00130 [101] - busy (100)
318         000001f3651e4f50: 00130 . 00060 [101] - busy (30)
319         000001f3651e4fb0: 00060 . 00060 [101] - busy (30)
320         000001f3651e5010: 00060 . 00060 [101] - busy (30)
321         000001f3651e5070: 00060 . 00060 [101] - busy (30)
322         000001f3651e50d0: 00060 . 00060 [101] - busy (30)
323         000001f3651e5130: 00060 . 00060 [101] - busy (30)
324         000001f3651e5190: 00060 . 00060 [101] - busy (30)
325         000001f3651e51f0: 00060 . 00060 [101] - busy (30)
326         000001f3651e5250: 00060 . 00060 [101] - busy (30)
327         000001f3651e52b0: 00060 . 00060 [101] - busy (30)
328         000001f3651e5310: 00060 . 00060 [101] - busy (30)
329         000001f3651e5370: 00060 . 00060 [101] - busy (30)
330         000001f3651e53d0: 00060 . 00060 [101] - busy (30)
331         000001f3651e5430: 00060 . 00810 [101] - busy (80f) Internal 
332         000001f3651e5c40: 00810 . 01cb0 [101] - busy (1caf) Internal 
333         000001f3651e78f0: 01cb0 . 00130 [101] - busy (108)
334         000001f3651e7a20: 00130 . 000b0 [101] - busy (88)
335         000001f3651e7ad0: 000b0 . 00830 [101] - busy (800) Internal 
336         000001f3651e8300: 00830 . 00420 [101] - busy (3f0) Internal 
337         000001f3651e8720: 00420 . 00050 [101] - busy (20)
338         000001f3651e8770: 00050 . 00120 [101] - busy (f0)
339         000001f3651e8890: 00120 . 00050 [101] - busy (1a)
340         000001f3651e88e0: 00050 . 00200 [101] - busy (1d8)
341         000001f3651e8ae0: 00200 . 00070 [101] - busy (48)
342         000001f3651e8b50: 00070 . 00120 [101] - busy (f0)

          我們繼續執行【!heap -x 0000022b076de000】看看,

 1         0000022b0769c010: 42010 . 41ff0 [101] - busy (41fe0) Internal 
 2         0000022b076de000: 41ff0 . 00400 [101] - busy (3f0) Internal (我選的這個地址 3         0000022b076de400: 00400 . 41c00 [101] - busy (41bf0) Internal 
 4         0000022b07720000: 41c00 . 10fc0 [100]
 5         0000022b07730fc0: 10fc0 . 00040 [111] - busy (3d)
 6         0000022b07731000:      00b9e000      - uncommitted bytes.
 7 0:000> !heap -x 0000022b076de000(這個地址我是隨便選的 8 Entry             User              Heap              Segment               Size  PrevSize  Unused    Flags
 9 -------------------------------------------------------------------------------------------------------------
10 0000022b076de000  0000022b076de010  0000022a779a0000  0000022b07300000       400     41ff0        10  busy  internal

            說明,這裏必須使用【gflags】註冊跟蹤數據庫,否則這裏是沒有輸出的,第一次,可把我搞蒙了。

            我測試到這裏,沒有測試到我需要的結果,不知道原因爲什麼,和【一線碼農】視頻有差距。當我執行【!heap -x】 命令,沒有得到我想要的結果,所以後面執行【!heap -p -a】命令就沒有辦法執行了。

四、總結
    終於寫完了,這個系列也終於寫完了,我說的這個系列是基於視頻的這個系列,因爲我打算基於《Net 高級調試》這個本書,再出一個系列。底層的東西,一次肯定是理解不透的,需要深入、多次的操作和調試。學習過程真的沒那麼輕鬆,還好是自己比較喜歡這一行,否則真不知道自己能不能堅持下來。準備收拾心情,重新在寫一個系列,完全是基於書本的,把每個章節都寫出來,調試一下,感受一下,肯定收貨更多。好了,不說了,不忘初心,繼續努力,希望老天不要辜負努力的人。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章