C++-内存检测模块的实现
想实现一个独立的内存检测模块,在以后的项目中可以直接链接,主要想跟踪内存的申请,释放,报告本进程的内存占用情况,求达人给个思路。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
想实现一个独立的内存检测模块,在以后的项目中可以直接链接,主要想跟踪内存的申请,释放,报告本进程的内存占用情况,求达人给个思路。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(6)
可以在编码时为每种结构体内存申请添加计数,类似
enum mem_type {
MTYPE_LINE,
MTYPE_CIRCLE,
MTYPE_MAX,
};
然后开辟一个数组
unsigned int mem_cnt[MTYPE_MAX];
定义私有的malloc/free函数
void *mtype_alloc(enum mem_type type, size_t size)
{
void *ptr;
ptr = malloc(size);
if (ptr) {
mem_cnt[type]++;
}
return ptr;
}
void *mtype_free(enum mem_type type, void *ptr)
{
if (ptr) {
mem_cnt[type]--;
free(ptr);
}
}
这样只要打印数组值的大小就可以知道每种结构体申请的数量。
内存泄漏检查的原理不复杂,但实现起来要花不少功夫。他的实现原理就是接管已有的系统堆分配策略,并把已经分配好的堆放到自己管理的链表中,当释放堆时把堆块从你的链表中移除。当进程退出时,也就是从amin返回时,你管理的链表中的堆块就是内存泄漏了。
当然了,这里有很多技巧和细节需要注意,比如你需要额外记录内存块所对应的的文件名和行号,一般都是加在堆的尾部或头部,以便可以以明文的方式查找泄漏位置。
具体实现linux上没我有研究过,windows平台你以参考一下_CrtSetAllocHook接口,当发生堆的申请会触发回调,其它的实现就得自己来实现了。
执行期内存检测分为三种:
一种是嵌入调试代码,比如重载或接管new,或者allocate等.
一种是ApiHook,Hook堆和虚拟内存申请的函数,进行处理
大部分工具都是前两种.
但是还有很牛B的第三种,目前没有哪个工具有实现这种的,作为一种思路,可以参考.
就是指针引用搜索,原理是:先枚举所有堆,和私有内存,然后一个一个处理.比如当处理内存块A时,就在A以外的堆,私有内存,可执行文件data段以及所以线程ESP以上的栈中搜索该内存的指针,逐步搜索,直至有一个指针存在与线程ESP以上或者可执行文件data段为止.如果不存在这样一个指针链,则基本为泄漏(也有存在C++对象继承导致的引用的指针并非真实的申请内存起始地址的情况).
可以使用第一种方式,因为第二种方式不适合,原因是你是直接加到工程中的,通常使用第二中方式的是需要一个另外的程序主动启动目标进程,然后在目标进程代码没有开始执行时进行Hook,否则对全局类的构造函数是Hook不了滴.
重载new操作符吧,可以消除大部分情况下的内存泄露问题
其实已有现成的工具,Valgrind有个Memcheck工具,这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等,你可以看看这篇文章,应用 Valgrind 发现 Linux 程序的内存问题
内存检测有很多现有的工具,可以参看:
@如何捕获崩溃进程的内存转储
@常用的程序Debug手段有哪些?
@Linux平台下如何检测、调试C/C++程序内存泄漏?
win平台下:
如果想要自己实现一个独立模块,继续推荐chrome,工程中MemoryWatcher模块(dll)实现类似你要的东西,在win平台下是dll形式载入工程的,内嵌stackwalker,hook了win平台下常用的内存申请释放方法,对内存申请释放等进行记录。根据动态内存操作方式之间单一的层次关系(Windows平台下的内存管理),dll载入初始化的时候,对win平台下原有的内存申请方法进行了方法注入,调用内部实现的方法在进程堆上分配释放存储,完成了基本的申请释放跟踪。win平台下可以基于MemoryWatcher实现你所需要的功能,如果是linux平台,可能chrome的linux版也是有这个功能模块的,自行参考一下就好了。
win下的MemoryWatcher实现源码不怎么好看,因为实现了hook的方式而不是一般实现的方法重载,接触的就稍微底层一点点,不过应该可以满足你的需求。
应要求,稍微详述一下,贴一点代码:
最主要的几个类:MemoryWatcher,MemoryHook,CallStack(参考visualleakdetector,StackWalker)
MemoryWatcher 主要完成方法的hook,以及监测内存的分配与释放。