C++中内存泄露检测
2015-10-30 14:17
429 查看
内存泄露的关键就是记录分配的内存和释放内存的操作,看看能不能匹配。跟踪每一块内存的声明周期,例如:每当申请一块内存后,把指向它的指针加入到List中,当释放时,再把对应的指针从List中删除,到程序最后检查List就可以知道有没有内存泄露了。Window平台下的Visual Studio调试器和C运行时(CRT)就是用这个原理来检测内存泄露。
在VS中使用时,需加上
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
通过包括 crtdbg.h,将 malloc 和 free 函数映射到其“Debug”版本 _malloc_dbg 和 _free_dbg,这些函数将跟踪内存分配和释放。此映射只在调试版本(在其中定义了 _DEBUG)中发生。发布版本使用普通的 malloc 和 free 函数。
#define 语句将 CRT 堆函数的基版本映射到对应的“Debug”版本。并非绝对需要该语句,但如果没有该语句,内存泄漏转储包含的有用信息将较少。
_CrtDumpMemoryLeaks();
函数将显示当前内存泄露,也就是说程序运行到此行代码时的内存泄露,所有未销毁的对象都会报出内存泄露,因此要让这个函数尽量放到最后。
#define _CRTDBG_MAP_ALLOC
#include<crtdbg.h>
#include<iostream>
using namespace std;
int main()
{
char*str1= (char*)malloc(100);
char*str2 = (char*)malloc(50);
deletestr1;
//输出内存泄露信息
_CrtDumpMemoryLeaks();
return0;
}
由上述代码可知,申请了两块内存,仅释放了一块内存。
运行调试会在输出窗口中输出如下信息:
Detected memory leaks!
Dumping objects ->
d:\workspaces\vs_2013\effective_c++_projects\检测内存泄露\memoryleaks1.cpp(18): {144} normal block at 0x007B9D70, 50 bytes long.
Data: < > CD CD CD CD CD CD CD CD CDCD CD CD CD CD CD CD
Object dump complete.
如果没有#define _CRTDBG_MAP_ALLOC就会输出如下信息:
Detected memory leaks!
Dumping objects ->
{144} normal block at 0x00389D70, 50 bytes long.
Data: < > CD CD CD CD CD CD CD CD CDCD CD CD CD CD CD CD
Object dumpcomplete.
未定义 _CRTDBG_MAP_ALLOC 时,所显示的会是:
内存分配编号(在大括号内)。
块类型(普通、客户端或 CRT)。
十六进制形式的内存位置。
以字节为单位的块大小。
前 16 字节的内容(亦为十六进制)。
定义了 _CRTDBG_MAP_ALLOC 时,还会显示在其中分配泄漏的内存的文件。文件名后括号中的数字(本示例中为
18)是该文件内的行号。
当我们使用new分配内存时,即使加上宏定义#define _CRTDBG_MAP_ALLOC,也不会检测到程序中内存申请的位置(行号)。因为刚刚包含头文件和加宏定义(_DEBUG)只重载了malloc函数,并没有重载new操作符,所以要自己定义重载new操作符才能检测到泄露内存的申请位置。
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG //重载new
//FILE和LINE前后是两个——
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
char *str1 = NULL;
char *str2 = NULL;
str1=(char*)malloc(100);
str2=new char[50];
_CrtDumpMemoryLeaks();
return 0;
}
这样用new分配内存之后,运行调试程序,这样就会输出带分配内存而泄露的申请位置会,输出如下:
Detected memory leaks!
Dumping objects ->
d:\workspaces\vs_2013\effective_c++_projects\检测内存泄露\memoryleaks1.cpp(22) : {145} normal block at0x00619DE0, 50 bytes long.
Data: < > CD CD CD CD CD CD CD CD CDCD CD CD CD CD CD CD
Object dumpcomplete.
_CrtSetDbgFlag
如果程序总是在同一位置退出,调用 _CrtDumpMemoryLeaks 将非常容易。如果程序从多个位置退出,则无需在每个可能退出的位置放置对 _CrtDumpMemoryLeaks 的调用,而可以在程序开始处包含以下调用:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
该语句在程序退出时自动调用 _CrtDumpMemoryLeaks。必须同时设置 _CRTDBG_ALLOC_MEM_DF 和_CRTDBG_ALLOC_MEM_DF 两个位域,如上所示。
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG //重载new
//FILE和LINE前后是两个——
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
_CrtSetDbgFlag(_CRTDBG_MALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF)
char *str1 = NULL;
char *str2 = NULL;
str1=(char*)malloc(100);
str2=new char[50];
return 0;
}
这样就不需要显示调用_CrtDumpMemoryLeaks()函数,_CrtSetDbgFlag在文件结束时,会自动调用用_CrtDumpMemoryLeaks()。
在VS中使用时,需加上
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
通过包括 crtdbg.h,将 malloc 和 free 函数映射到其“Debug”版本 _malloc_dbg 和 _free_dbg,这些函数将跟踪内存分配和释放。此映射只在调试版本(在其中定义了 _DEBUG)中发生。发布版本使用普通的 malloc 和 free 函数。
#define 语句将 CRT 堆函数的基版本映射到对应的“Debug”版本。并非绝对需要该语句,但如果没有该语句,内存泄漏转储包含的有用信息将较少。
_CrtDumpMemoryLeaks();
函数将显示当前内存泄露,也就是说程序运行到此行代码时的内存泄露,所有未销毁的对象都会报出内存泄露,因此要让这个函数尽量放到最后。
#define _CRTDBG_MAP_ALLOC
#include<crtdbg.h>
#include<iostream>
using namespace std;
int main()
{
char*str1= (char*)malloc(100);
char*str2 = (char*)malloc(50);
deletestr1;
//输出内存泄露信息
_CrtDumpMemoryLeaks();
return0;
}
由上述代码可知,申请了两块内存,仅释放了一块内存。
运行调试会在输出窗口中输出如下信息:
Detected memory leaks!
Dumping objects ->
d:\workspaces\vs_2013\effective_c++_projects\检测内存泄露\memoryleaks1.cpp(18): {144} normal block at 0x007B9D70, 50 bytes long.
Data: < > CD CD CD CD CD CD CD CD CDCD CD CD CD CD CD CD
Object dump complete.
如果没有#define _CRTDBG_MAP_ALLOC就会输出如下信息:
Detected memory leaks!
Dumping objects ->
{144} normal block at 0x00389D70, 50 bytes long.
Data: < > CD CD CD CD CD CD CD CD CDCD CD CD CD CD CD CD
Object dumpcomplete.
未定义 _CRTDBG_MAP_ALLOC 时,所显示的会是:
内存分配编号(在大括号内)。
块类型(普通、客户端或 CRT)。
十六进制形式的内存位置。
以字节为单位的块大小。
前 16 字节的内容(亦为十六进制)。
定义了 _CRTDBG_MAP_ALLOC 时,还会显示在其中分配泄漏的内存的文件。文件名后括号中的数字(本示例中为
18)是该文件内的行号。
当我们使用new分配内存时,即使加上宏定义#define _CRTDBG_MAP_ALLOC,也不会检测到程序中内存申请的位置(行号)。因为刚刚包含头文件和加宏定义(_DEBUG)只重载了malloc函数,并没有重载new操作符,所以要自己定义重载new操作符才能检测到泄露内存的申请位置。
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG //重载new
//FILE和LINE前后是两个——
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
char *str1 = NULL;
char *str2 = NULL;
str1=(char*)malloc(100);
str2=new char[50];
_CrtDumpMemoryLeaks();
return 0;
}
这样用new分配内存之后,运行调试程序,这样就会输出带分配内存而泄露的申请位置会,输出如下:
Detected memory leaks!
Dumping objects ->
d:\workspaces\vs_2013\effective_c++_projects\检测内存泄露\memoryleaks1.cpp(22) : {145} normal block at0x00619DE0, 50 bytes long.
Data: < > CD CD CD CD CD CD CD CD CDCD CD CD CD CD CD CD
Object dumpcomplete.
_CrtSetDbgFlag
如果程序总是在同一位置退出,调用 _CrtDumpMemoryLeaks 将非常容易。如果程序从多个位置退出,则无需在每个可能退出的位置放置对 _CrtDumpMemoryLeaks 的调用,而可以在程序开始处包含以下调用:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
该语句在程序退出时自动调用 _CrtDumpMemoryLeaks。必须同时设置 _CRTDBG_ALLOC_MEM_DF 和_CRTDBG_ALLOC_MEM_DF 两个位域,如上所示。
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG //重载new
//FILE和LINE前后是两个——
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
_CrtSetDbgFlag(_CRTDBG_MALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF)
char *str1 = NULL;
char *str2 = NULL;
str1=(char*)malloc(100);
str2=new char[50];
return 0;
}
这样就不需要显示调用_CrtDumpMemoryLeaks()函数,_CrtSetDbgFlag在文件结束时,会自动调用用_CrtDumpMemoryLeaks()。
相关文章推荐
- 《C++ primer》英文第五版阅读笔记(三)——变量
- C++应用程序的编译过程
- 华为C++笔试题
- C++学习笔记---容器和算法
- C++学习笔记---基本内置类型
- C++学习笔记--GCC编译过程
- C/C++ 面试题---测试一下你的内功
- C++折半插入排序
- C++内存泄露检测
- C++学习笔记:如何学习C++?
- C语言存储类型及各存储类型作用域和生存域比较
- 模板的特化
- c语言中的结构体和共用体
- c++内存池工作原理
- 捕鱼和分鱼
- 图书管理系统
- C语言常用知识
- C++ string的一些操作 从简到深
- Comparison of Java and C++
- 日志库EasyLogging++学习系列(8)—— Verbose日志详解