Windows下C++软件调试——检测内存泄露
前言
之前在面一家公司的时候被问及到:当你接收同事的项目,项目之中可能存在内存泄露,而且代码能够正常的运行不会报错。在这种情况下找出该项目中可能存在的内存泄露问题(比如原同事只new了但是没有delete),该如何进行检测。这样的问题确实很实用,因为在软件编写的过程中不仅仅需要完成软件功能,更加重要的是代码的健壮性。
至于Linux平台下的内存泄露检测在这篇博客里面进行了介绍。
1. Win32平台下
对于堆上内存操作(new,malloc)的检测,可以使用在Win32平台使用_CrtDumpMemoryLeaks()函数对内存泄露进行检测,实现的代码如下
// MemoryLeak.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <crtdbg.h>
using std::cout;
using std::endl;
#define _CRTDBG_MAP_ALLOC
int _tmain(int argc, _TCHAR* argv[])
{
system("color f0");
int *p_array = new int[10];
_CrtDumpMemoryLeaks(); //检测内存泄露
system("pause");
return 0;
}
输出结果:
注意:_CrtDumpMemoryLeaks()函数在上面代码的使用中需要写在函数的末尾,这样才能够检测到。
// MemoryLeak.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <crtdbg.h>
using std::cout;
using std::endl;
#define _CRTDBG_MAP_ALLOC
#define My_new new(_NORMAL_BLOCK, __FILE__, __LINE__) //定义一个自定义的new
int _tmain(int argc, _TCHAR* argv[])
{
system("color f0");
int *p_array = My_new int[10];
_CrtDumpMemoryLeaks(); //检测内存泄露
system("pause");
return 0;
}
输出结果:
如果想要不将_CrtDumpMemoryLeaks()函数放在尾部,就需要提前做好配置,代码为(参考资料(中文))
// MemoryLeak.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <crtdbg.h>
using std::cout;
using std::endl;
#define _CRTDBG_MAP_ALLOC
#define My_new new(_NORMAL_BLOCK, __FILE__, __LINE__) //定义一个自定义的new
int _tmain(int argc, _TCHAR* argv[])
{
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)|_CRTDBG_LEAK_CHECK_DF);
system("color f0");
int *p_array = My_new int[10];
system("pause");
return 0;
}
输出结果:
_CrtDumpMemoryLeaks一般都在有怀疑是内存泄漏的代码后面调用,除了这个函数之外使用率会比较高的函数是_CrtMemCheckpoint, 设置一个内存检查点。这个函数会取得当前内存的运行状态;_CrtMemDifference,检查两种内存状态的异同; _CrtMemDumpAllObjectsSince,从程序运行开始,或者从某个内存检查点开始Dump出堆中对象的信息;还有就是_CrtDumpMemoryLeaks当发生内存溢出的时候Dump出堆中的内存信息 。
// MemoryLeak.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <crtdbg.h>
#include <errno.h>
using std::cout;
using std::endl;
#define _CRTDBG_MAP_ALLOC
#define My_new new(_NORMAL_BLOCK, __FILE__, __LINE__) //定义一个自定义的new
int _tmain(int argc, _TCHAR* argv[])
{
system("color f0");
_CrtMemState Sh1, Sh2, Sh_Diff;
int* p_array1 = My_new int[10];
_CrtMemCheckpoint(&Sh1); //设置第一个内存检查点
int* p_array2 = My_new int[10];
memset(p_array2, 0, sizeof(int)*10);
_CrtMemCheckpoint(&Sh2); //设置第二个内存检查点
_CrtMemDifference(&Sh_Diff, &Sh1, &Sh2); //检查变化
_CrtMemDumpAllObjectsSince(&Sh_Diff); //Dump变化
system("pause");
return 0;
}
输出结果:
2. MFC环境平台下
Debug版本的MFC本身就提供一部分的内存泄漏检查。 大部分的new 和delete没有配对使用而产生的内存泄漏,MFC都会产生报告。这个主要是因为MFC重载了Debug版本的new 和delete操作符, 并且对前面提到的API函数重新进行了包装。在MFC类库中检查内存泄漏的Class就叫 CMemoryState,它重新包装了了_CrtMemState,_CrtMemCheckPoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince这些函数。并对于其他的函数提供了Afx开头的函数,供MFC程序使用。比如 AfxCheckMemory, AfxDumpMemoryLeaks 这些函数的基本用法同上面提到的差不多。 CMemoryState和相关的函数的定义都在Afx.h这个头文件中。
一般在*.cpp文件中会出现下面几行代码
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
这是对DEBUG_NEW的定义
#define DEBUG_NEW new(THIS_FILE, __LINE__)
相当于MFC已经包装好了,只需要使用就好了。下面是我写的一个测试用例
void CFile_TransDlg::OnBnClickedButtonTest()
{
// TODO: 在此添加控件通知处理程序代码
int* p_array = new int[10];
AfxDumpMemoryLeaks();
}
输出结果:
相关文章
- Windows下Nginx的启动、停止等命令&Nginx 配置多域名&windows下设置Nginx开机自动启动
- Windows下安装Code::Blocks 13.12进行C/C++开发
- Windows下pip安装包报错:Microsoft Visual C++ 9.0 is required Unable to find vcvarsall.bat
- C++ Windows编程中WPARAM等数据类型在32位和64位系统中的差异
- Open3D(C++) 计算点到平面的距离
- 蓝桥杯官网 试题 PREV-251 历届真题 补给【第十一届】【决赛】【研究生组】【C++】【C】【Java】【Python】四种解法
- windows server 2008 安装Microsoft ActiveSync 6.1提示缺少一个Windows Mobile设备中心所须要的Windows组件
- C++学习心得与c语言到c++衔接技巧
- VS项目出现WINDOWS.H already included. MFC apps must not #include <Windows.h>
- C++每日面试之delete this 合法吗?
- C++ std::multiplies实现无视类型执行乘法
- C++读写excel表格数据(LibXL for Windows) v3.6.5 正式特别版(附补丁)
- AI模型C++部署:ubuntu安装Cython并使用C/C++调用python动态库【附加c++与python互相调用算法demo程序接口的源码】
- C++使用技巧(二):C++ 类 & 对象的简单使用
- 嵌入式linux开发,C/C++跨平台开发,宏定义,条件编译区分windows和linux
- C/C++,windows下编译报错:error C3861: “strcasecmp”: 找不到标识符
- VC++如何通过代码自动弹出Windows系统的一些窗口(附源码)
- Windows下用Eclipse搭建C/C++开发环境
- C++ WINDOWS下 wchar_t *和char * 相互转化总结篇
- C++之IDE:Windows环境下基于MyEclipse软件配置C/C++开发环境
- c++检测cpu内核的数目
- C++下实现目录的遍历、创建及删除
- C/C++,windows下编译报错:error C3861: “strcasecmp”: 找不到标识符
- 跟老菜鸟学C++-蔡军生-专题视频课程