c/c++通用内存泄漏检测框架GMFD(General Memory Fault Detection Framework)
http://qa.baidu.com/blog/?p=171
1 背景:
x86平台有完善的用户态检测内存工具比如valgrind等,可以监控程序运行中详细的内存信息,从而精确定位内存问题。然而随着新平台的快速诞生(比如Tilera的TilePro64 CPU),这些工具不能被及时地移植,导致新平台缺乏相应的手段来定位内存错误,如内存越界,泄漏等,而只能使用粗粒度的方法top,free 等指令观察进程的动态内存总额。其缺点是粒度太粗,而且内存的总数变化有很多原因引起,在复杂的系统里,很难精确定位内存问题的根源,甚至会漏报错报,这严重影响了新平台(如Tilera)开发与测试的效率。针对这个问题,我们提出了一个通用的新平台针对c/c++内存错误检测框架。
该框架可适用于任何平台。其通过重写标准库的内存分配和释放函数(如malloc, new, new[], free,delete,delete[]等), 以及维护一个全局的内存分配map数据结构实现。重写后的内存分配比如my_malloc首先调用系统malloc功能,然后记录每一次malloc执行过程中的内存操作信息(包括文件名、行号以及内存尺寸,函数调用栈),以指针值为 key值,存进维护的全局map表。而重写的my_free则是根据传入的指针值在 map 中查找相应的数据项并将之删除,而后调用系统的free 将指针所指向的内存块释放。这样当程序退出的时候,map 中的剩余的数据项就是我们期望检测的内存泄漏信息。我们可以输出泄漏内存块的详细日志,比如文件名,行号等等。这将大大提高类似Tilera平台的内存问题追查效率,提高开发和测试的速度和质量。
2 基本原理:
1) 通过重写非共享内存分配释放函数malloc, new, new[],free,delete,delete[]截获 它们在执行过程中的内存操作信息。重载形式如下:
void* malloc( size_t nSize, char* pszFileName, int nLineNum )
void* new( size_t nSize, char* pszFileName, int nLineNum )
void* operator new[]( size_t nSize, char* pszFileName, int nLineNum )
void free( void *ptr )
void delete( void *ptr )
void operator delete[]( void *ptr )
2) 通过重写共享内存分配释放函数mspace_malloc,mspace_free,重写形式如下:
void* my_mspace_malloc( mspace msp,unsigned int Size, char* pszFileName, int nLineNum )
void my_mspace_free(mspace msp, void *ptr )
3) 我们对malloc, new, new[],mspace_malloc进行了重载,参数包括size_t nSize、文件名和行号,这里的文件名和行号就是这次malloc, new, new[],mspace_malloc操作符被调用时所在的文件名和行号,这个信息将在发现内存泄漏时输出,以帮助定位泄漏具体位置。对于 free,delete,delete[],mspace_free参数为指针地址。
3 实例:
以My_malloc, My_free为例,重写函数结构如下:
1. 在重写的my_malloc函数版本中,我们将调用malloc 的原始版本并将相应的 size_t 参数传入,然后,我们将malloc的原始版本返回的指针值以及该次分配所在的文件名和行号信息记录下来,这里采用STL 的 map数据结构存储,以指针值为 key 值,文件名,行号等信息作为一个结构体是value值。
My_free重写函数结构如下:
2. 当my_free 被调用时,我们根据传入的指针值在 map 中找到相应的数据项并将之删除,而后调用 free 将指针所指向的内存块释放。这样当程序退出的时候,map 中的剩余的数据项就是我们企图检测的内存泄漏信息。
4 实现关键点:
1) 如何取得内存分配代码所在的文件名和行号?
利用 C 的预编译宏 __FILE__ 和 __LINE__,这两个宏将在编译时在指定位置展开为该文件的文件名和该行的行号
2) 利用宏定义开关决定走普通分支还是内存检测分支?
#if defined( MEM_DEBUG )
#define malloc DEBUG_MALLOC
#define free DEBUG_FREE
#endif
3) 何时创建用于存储内存数据的 map 数据结构,如何管理,何时打印内存泄漏信息?
设计一个类来封装这个 map 以及对它的插入删除操作,然后构造这个类的一个全局对象(appMemory),在全局对象(appMemory)的构造函数中创建并初始化这个数据结 构,而在其析构函数中对数据结构中剩余数据进行分析和输出。new 中将调用这个全局对象的 insert 接口将指针、文件名、行号、内存块大小等信息以指针值为 key 记录到 map 中,在delete 中调用 erase 接口将对应指针值的 map 中的数据项删除,同时对 map 的访问需要进行互斥同步,因为同一时间可能会有多个进程进行堆上的内存操作。
4) 如何为非共享内存申请map?如何为共享内存申请map?非共享内存的map,对于多进程则有多个map,可按(3)的方法处理。而对于共享内存,可能A进程申请到B进程才释放,但是每个进程一个map,我们去扫描这些每个map时就会出现误报的现象,因此需要采取将map放入共享内存方法:我们申请一块共享内存区域为map,这个map对各进程是共享的。当程序中各进程调用共享内存时,将各进程分配的指针及文件名行号等详细信息存进这共享的map。程序结束时,扫描该共享的map,就能得到未释放的信息。将 map放入共享内存使用c++标准库时需要我们自己实现一个基于共享内存的allocator,替换map默认的allocator,在这个allocator中实现map的内存分配方案。也可以使用boost库(1.35以上版本),它增加了一个叫做boost::interprocess的库,具体可参考http://blog.cong.co/stl-alloc.html
5) 如何使用该工具?
内存泄露检测框架提供接口libmemck.h,内容如下

在被测试程序里包含如下代码即可使用

6) 何时如何捕获信号,生成leak文件?
定义一个全局的类得对象,在该类得构造函数里通过signal函数捕获SIGINT、SIGABRT、SIGFPE、SIGTERM信号,当捕获到这些信号其中之一时,开始扫描map并将map剩余信息写入leak文件展示。
7) 对临界资源的控制?
共享内存的各进程共享的map,各进程间进行读写操作需要加锁,我们这里采用的是信号灯实现。
非共享内存各个进程对应的map,在各进程进行插入删除操作时也需要加锁实现
8) 程序中malloc作为函数指针?
由于将原型malloc(size)重写为my_malloc(size,__FILE__,__LINE__),这样由于函数类型不一致,导致程序调用该工具时编译无法通过,真对这种情况的解决办法为:重写malloc(size)为my_malloc_p(size)这样除了文件名和行号无法得知外,泄露的多少内存可以报出。
(作者:Wdan)
c/c++通用内存泄漏检测框架GMFD(General Memory Fault Detection Framework)的更多相关文章
- 为什么各大厂自研的内存泄漏检测框架都要参考 LeakCanary?因为它是真强啊!
请点赞关注,你的支持对我意义重大. Hi,我是小彭.本文已收录到 GitHub · AndroidFamily 中.这里有 Android 进阶成长知识体系,有志同道合的朋友,关注公众号 [彭旭锐] ...
- 【转】简单内存泄漏检测方法 解决 Detected memory leaks! 问题
我的环境是: XP SP2 . VS2003 最近在一个项目中,程序退出后都出现内存泄漏: Detected memory leaks! Dumping objects -> {98500} n ...
- 【Visual Studio】简单内存泄漏检测方法 解决 Detected memory leaks! 问题(转)
原文转自 http://blog.csdn.net/u011430225/article/details/47840647 我的环境是: XP SP2.VS2003 最近在一个项目中, 程序退出后都出 ...
- Android 内存泄漏检测工具 LeakCanary(Kotlin版)的实现原理
LeakCanary 是一个简单方便的内存泄漏检测框架,做 android 的同学基本都收到过 LeakCanary 检测出来的内存泄漏.目前 LeakCanary 最新版本为 2.7 版本,并且采用 ...
- Android 性能优化之内存泄漏检测以及内存优化(中)
https://blog.csdn.net/self_study/article/details/66969064 上篇博客我们写到了 Java/Android 内存的分配以及相关 GC 的详细分析, ...
- android 内存泄漏检测工具 LeakCanary 泄漏金丝雀
韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha 313134555@qq.com 内存泄漏检测工具 android 内存泄漏检测工具 ======== 内存泄漏 就是 无用的对 ...
- 【转】Unix下C程序内存泄漏检测工具Valgrind安装与使用
Valgrind是一款用于内存调试.内存泄漏检测以及性能分析的软件开发工具. Valgrind的最初作者是Julian Seward,他于2006年由于在开发Valgrind上的工作获得了第二届Goo ...
- C++程序内存泄漏检测方法
一.前言 在Linux平台上有valgrind可以非常方便的帮助我们定位内存泄漏,因为Linux在开发领域的使用场景大多是跑服务器,再加上它的开源属性,相对而言,处理问题容易形成“统一”的标准.而在W ...
- 利用Android Studio、MAT对Android进行内存泄漏检测
利用Android Studio.MAT对Android进行内存泄漏检测 Android开发中难免会遇到各种内存泄漏,如果不及时发现处理,会导致出现内存越用越大,可能会因为内存泄漏导致出现各种奇怪的c ...
随机推荐
- 一些yuv视频下载地址
因为测试需要下载一些yuv视频地址,现存一个可以下载yuv视频的地址以备后用 http://trace.eas.asu.edu/yuv/index.html ftp://ftp.ldv.e-techn ...
- 邁向IT專家成功之路的三十則鐵律 鐵律十六:IT人交友之道-單純
元曲知名的作家 白樸,曾在沉醉東風﹒漁夫一文創作中,寫道:「雖無刎頸交,卻有忘機友」.IT人交朋友應首重在單純而非廣泛,因為實際上越複雜的朋友圈,只會為你的工作以及生活帶來許多不必要的麻煩.至於男女朋 ...
- iOS开发 编码规范
转至 http://www.cnblogs.com/celestial/archive/2012/06/30/2571417.html 编码规范 一.文档结构管理 1.建立Libraries文件夹 ...
- PS 如何用制作键盘图标
1 键盘可以大致分为笔记本键盘和台式机键盘,颜色一般是黑色或白色.不同的键盘,拍摄角度不同(俯视或者平视)得到的效果也不一样.一般我们根据自己需要得到需要的键盘形式.比如下面别人制作的一套立体键盘,立 ...
- andrid对不能导入的类,知道类路径怎样使用该类
andrid对不能导入的类,知道类路径怎样使用该类?使用java的反射机制. 下边是一个样例. MTK平台对Android源生的Telephone接口进行了扩展,加入了一个TelephonyManag ...
- Unix系统介绍
一.基础知识 操作系统 用户与计算机硬件之间的界面,是控制.管理计算机内各种硬件与软件资源.它是一个多用户.多任务.分时的操作系统. 对于分时系统:假如a进程需要16个时间片,现在根据优先级只分配了1 ...
- C语言-多重背包问题
多重背包问题 问题:有N种物品和一个容量为V的背包.第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 分 ...
- Linux安装Java/Maven
所需文件:jdk 下载 安装Java INSTALL_PATH=/opt/soft TAR_FILE=/mnt/d/resources/soft/jdk-8u152-linux-x64.tar.gz ...
- mysql drop table命令使用总结
drop性能 drop table(innodb引擎) 数量2000w,只需要5m
- 点击选中/取消选中flag
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...