Windows平台下c++ 内存泄漏检查的办法(如VLD)

49 篇文章 2 订阅
13 篇文章 1 订阅

1. VC自带的CRT:_CrtCheckMemory   调试器和 CRT 调试堆函数

主要适用于:win32,在mfc平台直接使用AfxDumpMemoryLeaks。不需要引用头文件和define任何东西

  该函数只在Debug版本才有用,当在调试器下运行程序时,_CrtDumpMemoryLeaks 将在“Output(输出)”窗口中显示内存泄漏信息。但是这个函数只能输出是否有内存泄漏,并不能定位到哪里出现了内存泄漏,因此我们需要参考mfc的方式来加入文件名称和代码行号。

一是包含调试堆函数库文件:

#include<crtdbg.h>

二是在需要检测内存泄漏的地方添加下面这条语句来输出内存泄漏信息:

_CrtDumpMemoryLeaks();

最好在代码中增加

#ifdef _DEBUG

#define new  new(_NORMAL_BLOCK, __FILE__, __LINE__)

#endif

宏定义,可以输出内存泄漏具体的文件位置信息。

#include<crtdbg.h>
#ifdef _DEBUG
#define new   new( _NORMAL_BLOCK, __FILE__, __LINE__)
#endif

int main()
{
    int* p = new int[10];
    _CrtDumpMemoryLeaks();
    return 0;
}

注意:如果程序总是在同一位置退出,调用 _CrtDumpMemoryLeaks 将非常容易。 如果程序从多个位置退出,则无需在每个可能退出的位置放置对_CrtDumpMemoryLeaks 的调用,而可以在程序开始处包含以下调用:

1

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

该语句在程序退出时自动调用 _CrtDumpMemoryLeaks。 必须同时设置 _CRTDBG_ALLOC_MEM_DF 和 _CRTDBG_LEAK_CHECK_DF 两个位域。

2.使用Visual Leak Detector(VLD)

VLD的最新版本为2.5.1,下载地址: VLD2.5.1。这个是别人弄好的下载。

或者使用该链接: https://pan.baidu.com/s/12GUr8MhUEzSO1YYTTS4Edg 提取码: 6rgj 

下载到的软件是:vld-2.5.1-setup.exe 。安装后,其安装目录为:

也可以到官网下载,下载地址为:https://kinddragon.github.io/vld/

配置VLD

打开VS2017,创建一个新工程,在资源管理器中项目右键,点击属性,进入项目属性页进行配置,用这种方法配置只能在本项目中使用VLD。若想一劳永逸,使所有项目都能使用VLD,则需要从属性管理器中进入“Microsoft.Cpp.x64.user”属性页(64位)或者“Microsoft.Cpp.Win32.user”属性页(32位)。本文从项目属性页对其进行配置。
设置 配置属性->VC++目录->包含目录:安装目录\include
设置 配置属性->VC++目录->库目录:安装目录\lib

注意事项:

1.不需要在链接器->输入->附加依赖项中添加xx.lib 文件

2.也不需要把dll放在运行目录下

如果是在安装exe时,选择把vld安转到vs环境中,会自动为项目设置继承,不需要再手动添加include和lib文件了,相当于跳过这一步。

 定位显示行号

配置属性->链接器->所有选项->生成调试信息 选择“生成经过优化以共享和发布的调试信息(/DEBUG:FULL)”,然后点击确定

在这里插入图片描述

另外还有一种办法显示行号:没测试过

需要更新dbghelp.dll,具体方法为:将VS2017 的dbghelp放到VLD里,替换VLD目录下的dbhelp.dll

VS2017 的dbghelp的路径为:

%programfiles(x86)%\Microsoft Visual Studio\2017\版本类型\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions\Cpp
 

 添加头文件

如果是没有预编译头,直接在main函数所在的cpp最前面加上#include "vld.h",

 若是有预编译头且是mfc程序,这最好在预编译头里#include <afxwin.h>前加上#include "vld.h"

如即一般放在stdafx.h或者pch.h文件前面位置。也就满足 如果有include"stdafx.h",则#include "vld.h"放在其后,否则放在最前面。

这个时候如果代码路径里没有中文,应该就可以正常使用了。但是如果有中文的话可能会出现:无法显示Call Stack文,得不到具体泄露的位置的问题。解决方法为:编辑VLD安装目录下的配置文件vld.ini,将ReportEncoding = ascii改为ReportEncoding = unicode就可以了。

测试现象和结果

 同时默认的情况下,会在源码工程目录下生成memory_leak_report.txt报告

 

如果有了调试信息,但在源码工程目录下没看到memory_leak_report.txt。是因为vld.ini 文件缺省配置为ReportTo = debugger 。应该改成ReportTo = both。

如果同时exe和多个dll,需要在每个exe和dll都要#include "vld.h",这样才能有内存泄漏日志产生。

如果只设置dll有#include "vld.h",并且产生了内存泄漏日志,则日志保存在dll的源码工程下,否则在exe的源码工程下。

注意事项:

1 如果有include"stdafx.h",则include <vld.h>放在其后,否则放在最前面
2 VLD只在debug版本有效
3 如果想将产生的日志保存到文件中,需要将vld.ini(VLD安装目录下)复制到可执行文件目录下,
然后作如下修改:
ReportFile =.\memory_leak_report.txt 

ReportTo = both   //设置为both,才能会在源码工程目录下生成报告

4.但是只支持MSVC编译器,不支持MingGW编译器。

原理:

在VisualC++中内置工具CRT Debug Heap工具,在使用Debug版本分配内存时,它会在内存块中记录分配该内存的文件名和行号。当程序退出时CRT会在main函数返回时做一些清理工作,此时检查调试堆内存,如果仍然有内存没释放,则一定存在内存泄漏问题。从这些没有被释放的内存块的头中可以得到文件名和行号。这种静态的方法可以检查出内存泄漏,但是不知道泄漏究竟是怎么发生的,也不知道该内存分配语句是如何被执行到的,想要了解这些必须对内存分配过程进行动态跟踪。VLD就是这样做的,在每次内存分配的时候记录其上下文,当程序退出时对检测到的内存泄漏查找其上下文信息,并转换成报告输出到Output中

Visual Leak Detector的工作分为3步

1)首先在初始化注册一个钩子函数;

2)然后在内存分配时该钩子函数被调用以记录下当时的现场;

3)最后检查堆内存分配链表以确定是 否存在内存泄漏并将泄漏内存的现场转换成可读的形式输出。

3.VS2017的Debug下的诊断工具

简单的程序可以实现记录快照和对比查找泄露位置,但是复杂的程序快照记录没问题,不过对比快照的时候会出现卡住的情况

4.神器:VS2017性能探查器的内存使用率分析(ALT+F2或者菜单调试->性能探查器)

可以做快照对比,能支持Debug和Release,使用后感觉应该是目前我用过最方便直观的内存泄露检测工具。

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C VLD(Visual Leak Detector)是一个针对C/C++程序的内存泄漏检测工具。内存泄漏指的是程序运行时分配的内存没有被释放,造成内存的浪费。下面我将分别介绍C VLD内存泄漏的原因及解决办法内存泄漏的原因主要有以下几点: 1. 未正确释放分配的内存:程序中使用了malloc、calloc等函数动态分配内存,但在使用完后未调用free进行释放,导致内存泄漏。 2. 函数返回值未释放:在函数中使用malloc等函数分配内存,但在函数返回后没有进行释放,使得此内存无法被利用。 3. 指针重复赋值:当一个指针值被重复赋值时,之前分配的内存就无法被释放,从而引起内存泄漏。 4. 被动态分配的内存忘记释放:自定义的数据结构中使用了malloc或者new分配的内存,在数据结构销毁之前未进行释放,导致内存泄漏。 解决内存泄漏办法可以是: 1. 在每次动态分配内存后,确保及时释放:使用free或者delete运算符进行内存释放。 2. 遵循“谁分配谁释放”的原则:在哪里分配内存,在哪里释放内存。 3. 防止内存重复赋值:使用指针前,确保之前分配的内存已被释放。 4. 使用智能指针:C++提供了智能指针的机制,如shared_ptr和unique_ptr,它们可以自动管理内存,减少手动释放内存的疏忽。 在使用C VLD工具时,可以通过代码编译时在源代码中包含vld.h头文件,并将vld.lib或者vld_dlls.lib添加到代码的链接库中。然后在程序运行时,vld.dll会自动加载并对内存泄漏进行检测,输出相应的信息。通过定位泄漏的位置,可以针对性地修复代码中的问题,最终解决内存泄漏

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值