2

PerfView专题 (第二篇):如何寻找 C# 中的 Heap堆内存泄漏 - 一线码农

 1 year ago
source link: https://www.cnblogs.com/huangxincheng/p/16580721.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

上一篇我们聊到了如何去找 热点函数,这一篇我们来看下当你的程序出现了 非托管内存泄漏 时如何去寻找可疑的代码源头,其实思路很简单,就是在 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即可,这么做的目的时拦截 HeapAllocHeapFree 方法,截图如下:

b3412103b71b4fa79c1e8380ff0de230~tplv-k3u1fbpfcp-zoom-1.image

稍等 15s 之后,打开 Memory / Net OS Heap Alloc Stacks 选项卡。

b3083df637f24c24b1147889aeb789bf~tplv-k3u1fbpfcp-zoom-1.image

接下来切到 CallTree 选项卡,清除掉 GroupPats 中的条件,观察各自的调用栈,截图如下:

499a99ace5904383be0cf4c7e3b9400f~tplv-k3u1fbpfcp-zoom-1.image

从图中的 inc % 列可以看到,calc_size 方法的 分配权重量 占 总分配量的 99.9% ,这就说明此方法有很大的嫌疑,最后就是查看源码了哦。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK