一:背景 上一篇我們聊到瞭如何去找 熱點函數,這一篇我們來看下當你的程式出現了 非托管記憶體泄漏 時如何去尋找可疑的代碼源頭,其實思路很簡單,就是在 HeapAlloc 或者 VirtualAlloc 時做 Hook 攔截,記錄它的調用棧以及分配的記憶體量, PerfView 會將這個 分配量 做成一個 ...
一:背景
上一篇我們聊到瞭如何去找 熱點函數
,這一篇我們來看下當你的程式出現了 非托管記憶體泄漏
時如何去尋找可疑的代碼源頭,其實思路很簡單,就是在 HeapAlloc 或者 VirtualAlloc 時做 Hook 攔截,記錄它的調用棧以及分配的記憶體量, PerfView 會將這個 分配量 做成一個 權重
,最後可以根據 權重
高低來找到有問題的調用棧。
二:案例演示
為了方便講述,我們演示一個 Windows 的 Nt堆 記憶體泄漏,讓 C# 調用 C++ 代碼時故意泄漏記憶體,代碼如下:
#include <iostream>
extern "C"
{
_declspec(dllexport) int calc_size(int size);
}
int calc_size(int size) {
int* buffer = new int[size];
return 2 * size;
}
然後在 C# 中導入這個 C++ 的 dll。
internal class Program
{
[DllImport("ConsoleApplication2.dll", CallingConvention = CallingConvention.Cdecl)]
extern static int calc_size(int size);
static void Main(string[] args)
{
for (int i = 0; i < int.MaxValue; i++)
{
var size = calc_size(1000);
Console.WriteLine($"i={i}");
}
}
}
接下來把程式跑起來,再打開 Perfview,在 OS Heap Process
輸入框填入進程號19404,監控 15s然後 Start Collection
即可,這麼做的目的時攔截 HeapAlloc
和 HeapFree
方法,截圖如下:
稍等 15s 之後,打開 Memory / Net OS Heap Alloc Stacks
選項卡。
接下來切到 CallTree
選項卡,清除掉 GroupPats
中的條件,觀察各自的調用棧,截圖如下:
從圖中的 inc %
列可以看到,calc_size
方法的 分配權重量
占 總分配量的 99.9%
,這就說明此方法有很大的嫌疑,最後就是查看源碼了哦。