PerfView专题 (第二篇):如何寻找 C# 中的 Heap堆内存泄漏
一:背景
上一篇我们聊到了如何去找 热点函数
,这一篇我们来看下当你的程序出现了 非托管内存泄漏
时如何去寻找可疑的代码源头,其实思路很简单,就是在 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%
,这就说明此方法有很大的嫌疑,最后就是查看源码了哦。
PerfView专题 (第二篇):如何寻找 C# 中的 Heap堆内存泄漏的更多相关文章
- PerfView专题 (第九篇):洞察 C# 中的 LOH 内存碎片化
一:背景 在 内存泄漏 的系列问题中,有一类问题是 内存碎片化 导致的,而且这种更容易发生在 LOH 上,因为它默认不开启 对象压缩,一般遇到这种情况,优先让朋友执行下面的代码应急. GCSettin ...
- 解析Java的JNI编程中的对象引用与内存泄漏问题
JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互——在 Java 程序中调用 native ...
- 关于 Unity 项目中的 Mono 堆内存泄露
关于 Unity 项目中的 Mono 堆内存泄露 题记:这是补一篇应该在将近一年前就应该写的记录,今天终于补上. 内存泄露是一个老话题了,之前我专门写过一篇 排查 Lua 虚拟机内存泄露 的文章,并且 ...
- 栈 堆 stack heap 堆内存 栈内存 内存分配中的堆和栈 掌握堆内存的权柄就是返回的指针 栈是面向线程的而堆是面向进程的。 new/delete and malloc/ free 指针与内存模型
小结: 1.栈内存 为什么快? Due to this nature, the process of storing and retrieving data from the stack is ver ...
- 【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化
C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 本文讨论了几种在使用动态内存分配时可以避免的陷 ...
- 5个Android开发中比较常见的内存泄漏问题及解决办法
android中一个对象已经不需要了,但是其他对象还持有他的引用,导致他不能回收,导致这个对象暂存在内存中,这样内存泄漏就出现了. 内存泄漏出现多了,会是应用占用过多的没存,当占用的内存超过了系统 ...
- PerfView专题 (第十篇):洞察 C# 终结队列引发的内存泄漏
一:背景 C# 程序内存泄漏的诱发因素有很多,但从顶层原理上来说,就是该销毁的 用户根 对象没有被销毁,从而导致内存中意料之外的对象无限堆积,导致内存暴涨,最终崩溃,这其中的一个用户根就是 终结器队列 ...
- 第二十三篇、使用NSURLSession时需要注意一个内存泄漏问题
如图1代码所示,初始化一个NSURLSession临时实例对象并由它发起一个网络请求.我们通过Instruments的Leaks工具会发现其存在内存泄漏和循环引用的地方,如图2所示. 通过NSURLS ...
- 在 Linux 平台中调试 C/C++ 内存泄漏方法(转)
由于 C 和 C++ 程序中完全由程序员自主申请和释放内存,稍不注意,就会在系统中导入内存错误.同时,内存错误往往非常严重,一般会带来诸如系统崩溃,内存耗尽这样严重的后果.本文将从静态分析和动态检测两 ...
随机推荐
- 检查MySQL主从复制运行状态
脚本思路: 1.使用MySQL客户端命令"mysql"直接在命令行中运行MySQL指令"show slave status\G;"来查看MySQL主从复制状态信 ...
- vue 下搭建ant design环境
之前用ant-design-vue组件在vue页面下使用 一不小心就会出现编译错误,网上不是搭建教程都是不太准确,现整理下 1.根据ant design vue 官网的假定条件 已经安装了nodejs ...
- @vue/cli3+配置build命令构建测试包&正式包
上一篇博客介绍了vue-cli2.x配置build命令构建测试包和正式包,但现在前端开发vue项目大多数使用新版@vue/cli脚手架搭建vue项目(vue create project-name) ...
- springboot 项目 运行rabbitmq(推送+消费)
准备 先下载windos版本的mq 「rabbitmq-server-3.9.13.exe」https://www.aliyundrive.com/s/VKB63ghAJZx 点击下载 1启动rabb ...
- 面试突击58:truncate、delete和drop的6大区别
在 MySQL 中,使用 truncate.delete 和 drop 都可以实现表删除,但它们 3 个的使用场景和执行效果完全不同,接下来我们来盘点一下. truncate.delete.drop区 ...
- JS:this关键字1
this 代表了当前的对象,哪个对象调用了this所在的函数,this就代表了哪个对象: 例1: function fn(){ var a = 1; console.log(this) } fn() ...
- MySQL 8.0 新特性梳理汇总
一 历史版本发布回顾 从上图可以看出,基本遵循 5+3+3 模式 5---GA发布后,5年 就停止通用常规的更新了(功能不再更新了): 3---企业版的,+3年功能不再更新了: 3 ---完全停止更新 ...
- 浅议.NET遗留应用改造
浅议.NET遗留应用改造 TLDR:本文介绍了遗留应用改造中的一些常见问题,并对改造所能开展的目标.原则.策略进行了概述. 一.背景概述 1.概述 或许仅"遗留应用"这个标题就比较 ...
- @RequestBody,@RequestParam是否能随意改变入参字母大小写
在工作中遇到了一个问题,很多接口有的入参是companyName,有的入参是companyname,实际上,这两入参能任意适配所有接口,甚至随意改变大小写! 1. @RequestBody是完全按照驼 ...
- sudoer文件配置错误修复
以错误配置权限为例,如果是sudoer文件内容配置错误,替换步骤(4)中相关命令即可 (1)建立两个ssh连接,分别记为A.B (2)A:echo $$获取ID (3)B:pkttyagent --p ...