内存泄漏检测
来源:互联网 发布:浙江出版联合集团知乎 编辑:程序博客网 时间:2024/05/29 04:49
内存泄漏检测
sf2gis@163.com
2013年5月14日
1 内存泄漏
1.1 定义
Memory leaks,也称存储渗漏。动态分配的内存空间,在使用完成后没有释放,导致程序一直占据该内存单元,直到程序结束。
当程序申请了一块内存,但指向这块内存的指针销毁了。那么这块内存无法释放,则此块内存泄漏了。
1.2 表现
内存泄漏导致程序占据的内存越来越多,直到程序结束或内存资源全部占用,系统崩溃。
1.3 分类
1.3.1 常发性
多次执行,每次都会有泄漏发生。
1.3.2 偶发性
特定环境下发生泄漏。
1.3.3 一次性
每次仅发生一块泄漏
1.3.4 隐式
程序不断申请内存,但却在程序结束时才释放,长时间运行时会产生与内存泄漏一样的效果。
1.4 避免
1.4.1 尽量减少手动分配内存,使用其它方式代替。
1.4.2 数组应使用stl容器代替。
1.4.3 尽量使用智能指针。
1.4.4 New和Delete的成对使用。这里要注意异常时要释放资源。
1.4.5 所有继承使用虚析构函数,所有接口使用定义这空的虚析构函数,避免无法级联析构造成内存泄漏。
2 内存泄漏检测
MS的官方支持MFC内存泄漏方法,其它C++文件也可以检测,但无法定位。
此方法可以将malloc和free用_malloc_debug和_free_debug替换,可以跟踪内存分配。如果检测到预定义的_CRT_MAP_ALLOC,则可以输出内存泄漏所在的代码位置。
2.1 概要步骤
1) 添加支持文件
2) 设置结束后内存泄漏检测
3) 多运行几次,确定固定的内存分配号
4) 根据输出的内存分配号,设置内存断点
5) 在运行到内存断点后,查看调用堆栈,找到泄漏点
2.1.1 示例
//check memory leak
#define _CRT_MAP_ALLOC
#include <cstdlib>
#include <crtdbg.h>
。。。
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
。。。
。。。
_CrtSetBreakAlloc(13810);
。。。
。。。
找到内存泄漏点并修复。
2.2 添加支持文件
#define _CRT_MAP_ALLOC//定位功能
#include <stdlib.h>//crtdbg支持库
#include <crtdbg.h>//内存泄漏检测库
注意顺序固定!
2.3 输出检测信息
_CrtDumpMemeryLeaks():输出检测信息,检测此前的内存泄漏状态。
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF):设置内存泄漏检测状态,这样可以在每次退出时自动测试,适用于多个可能出口的情况。
3 内存检测报告
3.1 报告格式
{内存分配序号} 块类型 block at 内存位置(16进制表示),内存泄漏数量 bytes long,Data:<前16字节内容> 每个字节的内容(16进制表示)。
3.1.1 注释
内存分配序号:当前内存块被依次分配的序号。
3.2 示例
{366}normal block at 0x0020FEA8, 200 bytes long. Data: < > CD CD CD CD CD CD CD CD CDCD CD CD CD CD CD CD
3.3 调试信息输出到输出窗口
3.3.1 格式
_RPTn(类型,内容,参数);n表示参数的个数。参数格式与printf格式相同。
变体有:_RPTFn(),_RPTWn(),_RPTFWn()。
类型有三种:
_CRT_WARN:在输出窗口显示。
_CRT_ERROR:以调试错误窗口形式显示。
_CRT_ASSERT:以调试断言错误窗口形式显示。
内容:格式化输出方式,与后面的参数对应。
参数:参数的数目要在_RPTn()中由n指定。
3.3.2 示例
_RPT0(_CRT_ERROR,"Type:_CRT_ERROR!");
_CrtMemDumpStatistics(&s1);
_RPT0(_CRT_ASSERT,"Type:_CRT_ASSERT");
_CrtMemDumpStatistics(&s2);
_CrtMemDifference(&s3,&s1,&s2);
_RPT1(_CRT_WARN,"%s","Type:_CRT_WARN\n");
4 内存分配号的使用:内存断点
内存分配号可以在Quick Watch、Watch或者代码中指定在内存分配到此号时,程序进入中断调试状态。
注意:由于内存分配号并不是保持不变的,所以在使用时,要注意此号是否会改变。
内存断点的从分配后的高次序向低次序进行调试,因为最后的内存泄漏可能导致其操作中其它的内存没有释放。
4.1 在代码中设置分配内存断点(静态断点)
在窗口中设置内存断点每次都要重新设置value值,操作步骤也比较麻烦,可以使用代码中设置断点。
_CrtSetBreakAlloc(value);或_CrtBreakAlloc= value;
两都效果相同。
如:_CrtSetBreakAlloc(366);与_CrtBreakAlloc= 366;效果是一样的。
4.2 在监视窗口中设置分配内存断点(动态断点)
4.2.1 首先确定自己的程序使用的C运行库类别
方法是程序Propertise -> C/C++ -> Code Generation-> Runtime Library选项,若为Multi-threaded Debug(/MTd),则为静态链接,若为Multi-threaded Debug DLL(/MDd),则为动态链接。
4.2.2 设置监视位置
然后按F11启动程序,程序会停在入口点。此时调出Watch窗口,动态设置监视的内存地址。
a) 静态链接 在name项中输入_crtBreakAlloc,在value项中输入你要定位的内存分配编号;
b) 动态链接 在name项中输入{,,msvcr100d.dll}_crtBreakAlloc,在value项中输入内存分配号。
注意:msvcr100d.dll是vc2010环境使用的Debug运行库dll,若你用的是其他版本vc,请换成对应版本的dll。
注意:这种方法每次运行都会重置value值为-1,所有要注意每次运行时设置value值。
4.2.3 调试程序
断点中断之后,就可以查看调用堆栈,找到中断位置的上下文,查找可能出现问题的位置。
5 内存块类型
内存块类型:自由块,忽略块,普通块,客户端块,CRT块。
自由块:处理内存中,可以被使用的块。
忽略块:被特殊标示的块。
普通块:程序中使用的自由存储块。
客户端块:MFC为需要析构对象创建的内存块。
CRT块:CRT内部使用的块。
6 内存状态比较
比较内存中各种内存块的数量,可以确定在不同时刻内存的使用状态,如果两个时刻的内存状态应该保持一致,则可以此为据确定有没有发生内存泄漏。
6.1 内存状态快照结构
_CRT_MEM_STATE:内存状态结构。
6.2 获取内存状态快照
_CrtMemCheckPoint (_CRT_MEM_STATE * m):将当前内存状态装入内存状态结构中。
6.3 导出内存状态快照
_CrtMemDumpStatistic(const _CRT_MEM_STATE * m):将当前内存状态输出到输出窗口中。
6.4 比较内存状态快照
_CrtMemDifference(_CRT_MEM_STATE * md,const_CRT_MEM_STATE * mold, _CRT_MEM_STATE * mnew):将新旧两个快照比较,将结构输出到差异状态md中。
6.5 示例
_CrtMemState s1,s2,s3;
_CrtMemCheckpoint(&s1);
char *p = new char[200];
_CrtMemCheckpoint(&s2);
_CrtMemDifference(&s3,&s1,&s2);
_CrtMemDumpStatistics(&s3);
7 Bounds Checker检测内存泄漏
Micro Focus公司出口的Dev PartnerBoundsChecker可以检测内存泄漏,能够集成到VS之中,运行时自动检测,使用方便。
7.1 下载安装BoundsCheck
版本:DevPartner Studio Visual C++ Edition 10.0(vs2010可用)
7.2 运行检测
点击BoundsCheck的运行检测按钮,进入BoundsCheck的检测运行状态。
7.3 查找修改
如果出现内存泄漏,根据提示,找到出现的源代码位置,进行检查,修改代码。
只需要修改代码中编辑的地方,系统自动填写的代码不用处理。
- CRT检测内存泄漏
- 内存泄漏检测
- 内存泄漏检测
- Linux内存泄漏检测
- C++内存泄漏检测
- 内存泄漏检测
- vc++内存泄漏检测
- MFC 内存泄漏检测
- 内存泄漏检测
- 内存泄漏的检测
- 检测内存泄漏
- 内存泄漏检测
- 如何检测内存泄漏
- 内存泄漏检测
- 内存泄漏检测
- windows检测内存泄漏
- VS 内存泄漏检测
- 检测内存泄漏
- C语言指针练习之不等长字符排序
- (二十一)中介者模式
- HDU 1242 Rescue(BFS+优先队列)
- SUSE12修改主机名方法
- 别把失眠不当回事
- 内存泄漏检测
- 设置程序运行期间使用dll的路径
- 3、目录操作
- Android IPC进程通信之Messager方式
- iOS OC语言: Block底层实现原理
- Ubuntu下 搭建Android5.1.1编译环境
- 统计字数问题
- 关于CSS浮动float属性的了解及清除浮动的方式
- 设计模式的学习