C++调试内存泄漏
Posted CodeBowl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++调试内存泄漏相关的知识,希望对你有一定的参考价值。
笔记:之前研究过如何定位内存泄漏,太长时间不用又忘记了,今天把它记下来!
学而时习之
内存泄漏的原因
C++和其他高级语言不同,需要自行管理内存,项目大\\调用多,容易内存泄漏.内存申请释放使用malloc/free和new delete两种方式。
有经验的程序员会对程序中申请内存的地方进行排查,例如malloc或者new关键字的地方进行跟踪,一种情况是我们按照程序逻辑进行了申请和释放,要提防程序在发生异常时没有如我们所期望的那样进行内存释放,此时也应当防止内存泄漏。
排查方法
windows CRT调试(Find memory leaks with the CRT library)
这是最方便的方法。
官方有详细使用描述:官网链接:Find memory leaks with the CRT Library - Visual Studio (Windows) | Microsoft Docs
使用案例:
// debug_new.cpp
// compile by using: cl /EHsc /W4 /D_DEBUG /MDd debug_new.cpp
#define _CRTDBG_MAP_ALLOC
#include <cstdlib>
#include <crtdbg.h>
#ifdef _DEBUG
#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
// Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the
// allocations to be of _CLIENT_BLOCK type
#else
#define DBG_NEW new
#endif
struct Pod
int x;
;
void main()
Pod* pPod = DBG_NEW Pod;
pPod = DBG_NEW Pod; // Oops, leaked the original pPod!
delete pPod;
_CrtDumpMemoryLeaks();//直接打印内存泄漏信息
定位更加准确的地址
//#ifdef _DEBUG
//#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
//#else
//#define DEBUG_CLIENTBLOCK
//#endif
//#define _CRTDBG_MAP_ALLOC
//#include <stdlib.h>
//#include <crtdbg.h>
//#ifdef _DEBUG
//#define new DEBUG_CLIENTBLOCK
//#endif
//_CrtMemState s1,s2,s3;
//_CrtMemCheckpoint(&s1);//记录s1处内存数据
//to do something
//_CrtMemCheckpoint(&s2);//记录s1处内存数据
//if (_CrtMemDifference(&s3, &s1, &s2))
// _CrtMemDumpStatistics(&s3);//内存泄漏,两处内存数据不一致,差异结果返回至s3,打印信息
VS2019自带的诊断工具,可在程序运行时打开诊断工具窗口-----》勾选内存使用率----》启用堆栈快照
VS2019自带的诊断工具,可在程序运行时打开诊断工具窗口-----》勾选内存使用率----》启用堆栈快照
类型视图能根据各种差异,点击左侧箭头所指的视图实例,可准确定位内存泄漏发生点。
VLD(Visual Leak Detector)
简介
Visual C++ 提供了内置的内存泄漏检测,但它的功能充其量只是最小的。此内存泄漏检测器是作为 Visual C++ 提供的内置内存泄漏检测器的免费替代品而创建的。以下是 Visual Leak Detector 的一些功能,内置检测器中不存在这些功能:
为每个泄漏块提供完整的堆栈跟踪,包括可用的源文件和行号信息。
检测大多数(如果不是全部)进程内内存泄漏类型,包括基于 COM 的泄漏和基于纯 Win32 堆的泄漏。
选定的模块(DLL 甚至主 EXE)可以从泄漏检测中排除。
提供泄漏块的完整数据转储(以十六进制和 ASCII 格式)。
可定制的内存泄漏报告:可以保存到文件或发送到调试器,并且可以包含可变级别的详细信息。
其他用于 Visual C++ 的售后泄漏检测器已经可用。但大多数真正流行的,如 Purify 和 BoundsChecker,都非常昂贵。存在一些免费的替代方案,但它们通常太具有侵入性、限制性或不可靠。 Visual Leak Detector 是目前唯一可免费使用的 Visual C++ 内存泄漏检测器,它将上述所有专业级功能整齐地打包在一个易于使用的库中
如何测试自己的项目呢
在自己的工程中引入vld.h文件,并在链接库中配置vld.lib库
设置当前工程为Debug模式,才能显示堆栈相关的调用信息
#### 例子
#include<stdlib.h>
#include<stdio.h>
#include <iostream>
#include <vld.h>
#include "three.h"
using namespace std;
class three
public:
three();
~three();
;
int main()
cout << "vld test begin" << endl;
int *one = new int[30];
char *two = new char[40];
three * tmp = new three();
return 0;
程序执行完之后会在终端显示内存泄漏的的个数,并同时会打印相关的内存泄漏的堆栈信息,当鼠标点击终端信息输出的位置时,同时会在上方代码指示哪一行出现内存泄漏。
参考资料
https://www.jb51.net/article/224934.htm
在网上看到的一种有趣的自己排查的方法
https://www.jb51.net/article/246468.htm
通过联想到内存的申请释放方式,申请和释放总是配对的,申请的大小也是预先知道的.**在内存申请申请释放的时候加上内存地址打印,当内存泄漏报错的时候就可以定位出错内存地址在哪个范围.**我加入了一个内存打印函数,把内存地址范围和时间都打印出来.
void DebugHeap(CString name, void * ptr,int size)
long Time = GetCurrentTime();
TRACE("========>heap name:%s,address [%p:%p],time:%d (ms)\\n", name,ptr,(char *)ptr + size,Time);
哈哈哈其实和系统提供的方法是相似的,凭借自己想到还是挺厉害的,但是不推荐。
以上是关于C++调试内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章