使用Visual Leak Detector排查内存泄漏问题

news2024/12/29 1:43:33

目录

1、VLD工具概述

2、下载并安装VLD

2.1、下载VLD

2.2、安装VLD

3、VLD安装目录及文件说明

3.1、安装目录及文件说明

3.2、关于32位和64位版本的详细说明

4、在工程中引入VLD

5、内存泄漏检测实例讲解

5.1、程序启动报错

5.2、启动调试,查看内存泄漏报告

5.3、vld.ini配置文件的使用

6、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章正在更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html       内存泄漏是C/C++程序一类常见的问题,内存泄漏的危害比较大,如果内存长时间的持续泄漏,则会导致Out of memory内存耗尽异常,程序进而发生崩溃闪退。对于大型软件来说,业务模块众多、设计复杂,排查起来可能会很费劲,可能使用多种排查手段都难以定位。我们有必要掌握多种排查内存泄漏的方法,在遇到问题时,一种方法无法定位,可以尝试使用其他手段去排查。今天我们来介绍一个内存泄漏工具Visual Leak Detector(简称VLD),详细讲述使用该工具排查内存泄漏问题的完整过程。本文考虑到很有朋友是开发新手,会讲的比较详细一些。

1、VLD工具概述

        Visual Leak Detector是一款用于C/C++的免费开源的内存泄露检测工具。相比较其它的内存泄露检测工具,它在检测到内存泄漏时有如下特点:

1)可以输出内存泄漏点的调用堆栈,在函数调用堆栈中会显示具体的文件名及代码行号;
2)可以显示泄露内存中的完整数据;
3)它不是独立运行的exe程序,是一个dll动态库,需要在项目工程中引入该库,并对代码进行重新编译;
4)它的源代码是开源的,使用GNU许可发布,并有详尽的文档及注释。对于想深入了解堆内存管理以及内存泄漏排查机制的读者,是个不错的选择。

       从使用的角度讲,VLD简单易用,对于使用者,只要自己的代码中包含VLD的头文件,并将VLD的dll库拷贝到exe主程序的目录中,在debug下正常运行程序就可以检测内存泄漏问题了。从研究角度上讲,VLD源代码是开源的,深入到源码中,可以学习堆内存分片与释放的原理、内存检查的原理机器内存操作的常用技巧等。

2、下载并安装VLD

       VLD当前的最新版本是2.5.1,进入VLD的官方页面,下载该版本即可。

2.1、下载VLD

       如果找到微软关于VLD的官方页面(https://marketplace.visualstudio.com/items?itemName=ArkadyShapkin.VisualLeakDetectorforVisualC),如下所示:

点击“Get Stated”按钮,进入VLD的github页面:

在页面底部点击vld-2.5.1-setup.exe的超链接去下载,中途会下载失败。

       可以到https://kinddragon.github.io/vld/页面,点击“Download Installer”按钮去下载,如下:

2.2、安装VLD

       先到网址上下载最新版本的Visual Leak Detector 2.5.1的安装包,下载完直接安装就可以了。在安装过程中会让选择是否将VLD添加到环境变量和Visual Studio中,此处不用勾选,不需要自动帮我们配置,我们在需要使用VLD时手动在项目中配置一下就好了。

3、VLD安装目录及文件说明

       VLD并不是一个独立运行的exe程序,只是一个dll库,所以VLD安装包中包含的是VLD编译好的.h头文件、.lib和.dll库文件,它并不是安装一个可以执行的exe程序,只是将这些释放到安装目录中。

3.1、安装目录及文件说明

       VLD默认是安装到路径C:\Program Files (x86)\Visual Leak Detector中的,我们可以到安装目录中去看一下,主要包含3个文件夹:

        include文件夹中放的是VLD库的头文件,如下:

       lib文件夹中存放的是vld.lib文件,有两个版本,一个是Win32的vld.lib,一个是Win64的vld.lib。bin文件夹中存放dll等二进制文件,如下所示:

同样也有32位和64位版本。

       类似的安装包,我们在编译libcurl开源代码时也会用到,libcurl库内部会调用到openssl开源库接口,但libcurl库源码中不提供openssl库,我们可以到网址中下载openssl安装包,该安装包中就是包含了openssl的库文件和头文件,即安装目录下就是释放出来的库文件和头文件。

3.2、关于32位和64位版本的详细说明

        使用IDE编译Windows程序时,可以编译32位的(对应x86),也可以编译64位的(对应x64)。32位Windows系统中只能运行32位程序,不能运行64位程序。64位Windows系统中可以运行64位程序,也可以运行32位程序(提供对32程序的兼容)。

        较老的Windows系统可能还是32位,比如部分Win7系统还是32位的。不过比较新的Win10、Win11系统全部都是64位系统了。很多软件为了兼容32位Windows系统,直接将软件编译成32位程序,这样程序在32位和64位Windows系统中都可以运行。

       也有不少程序,分别提供了32位安装包和64位安装包,这样用户可以根据自己的需要选择对应的版本安装。如果是32位Windows系统,则只能安装32位安装包;如果时64位Windows系统,则32位和64位安装包都可以安装。

       从开发者的角度,有两点需要注意一下:

1)系统32位和64位程序进程分配的虚拟内存大小有较大差异
        对于32位程序,系统会给启动的程序分配2的32次方的虚拟内存,即4GB。对于64位程序,系统会给程序进程分配2的64次方的虚拟内存,即虚拟内存非常大,比32位程序4GB的虚拟内存要大的多。对于32位程序,2GB是用户态的内存,2GB是内核态的内存,对于大型软件,运行过程中会占用较大的内存空间,有可能会出现虚拟内存不够用的情况,如果虚拟内存不够用,则会产生Out of memory内存耗尽的异常。之前我们在讲内存泄露时,也讲到过这个内存耗尽的异常。
2)位数不同的exe和dll库不能混用
       32位程序不能使用64位dll文件,64位程序不能使用32位dll文件,因为位数不同,寻址范围是不同的。32位程序要选用32位dll文件,64位程序要选用64位dll文件。所以VLD提供了32位和64位两个版本的库,使用者根据自己程序的位数,选择对应的版本。

4、在工程中引入VLD

       Visual Leak Detector不是一个exe可执行程序,和能直接运行的工具有所不同,它是一个dll动态库,需要集成到我们的代码中,重新编译代码,然后在程序运行的过程中进行检测。

       我们在引用VLD时,就像引用普通的dll库一样,先include库的头文件(vld.h),再引入库的.lib文件(vld.lib,编译链接时需要用到),然后将dll文件拷贝到exe主程序的目录中。

1) 包含vld.h头文件(用于编译)

       在包含vld.h头文件之前,需要将vld.h头文件所在的路径设置到工程属性中:C/C++ -> 常规,在附加包含目录中添加vld.h头文件所在的路径,如下所示:

这样编译代码时就会到上述路径下去找到vld.h头文件了。

2)引入vld.lib文件(用于链接)

       在引入vld.lib文件之前,需要将vld.lib文件所在的路径设置到工程属性中:链接器 -> 常规,在附加库目录中添加vld.lib文件所在的路径,如下所示:

这样编译链接时就会到上述路径中去找到vld.lib文件,进行链接了。此处,我们不用手动将vld.lib文件引入到工程代码中,因为vld.h头文件中已经帮我们自动引入了,如下所示:

3)拷贝vld.dll库文件到exe主程序目录中(用于运行)

      到安装目录下的bin文件夹中将dll及其他的文件拷贝到exe主程序的目录中。

      编译代码,运行程序,即可查看检测结果。

5、内存泄漏检测实例讲解

         之前创建了一个win32控制台工程TestMemLeak,然后在main函数中添加一行动态申请内存的代码,如下所示:

在main函数退出时故意没有释放内存,测试一下VLD的检测效果。

5.1、程序启动报错

       按上面讲的那样,将头文件和.lib文件的路径设置到工程中,然后将vld.h头文件包含进来。然后编译代码,启动调试,结果启动时报错了
弹出如下的提示框:

程序无法启动,对应的异常码为0xc0150002。

        为了搞清楚这个错误码的含义,直接在VS中输入之前熟悉的错误码宏:STATUS_STACK_OVERFLOW
然后go到对应的系统异常码定义的头文件中,对应的路径为:C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\ntstatus.h
尝试在该头文件中搜索异常码0xc0150002,果然找到了,如下:

系统无法处理应用程序中的绑定信息。难道是在拷贝bin目录下的文件时,不仅要拷贝vld_x86.dll,是不是要把目录下的其他文件也拷贝过去?
于是手动又将dbghelp.dll和Microsoft.DTfW.DHL.manifest拷贝到exe主程序的目录中,重新运行exe程序就好了,就不再报错了。

5.2、启动调试,查看内存泄漏报告

       因为main函数比较简单,进入后立即退出了,程序也就退出了。然后在Visual Studio的输出窗口中,看到了:Visual Leak Detector detected memory leaks!,即VLD检测到了内存泄漏,如下所示:

将发生内存泄漏的地址及大小打印了出来:

---------- Block 1 at 0x01497020: 1024 bytes ----------

同时也将泄漏代码所在线程的函数调用堆栈打印出来了,然后还将内存泄漏的那段内存中的内容显示出来了。双击图中的那行代码,就跳转到发生内存泄漏的那行代码:

5.3、vld.ini配置文件的使用

      在VLD的安装目录中还有个vld.ini配置文件,如下所示:

这个配置文件中可以对VLD进行一些配置,如果要用这个文件,需要将之拷贝到exe主程序的目录中。

       可以使用ReportTo配置项,默认情况下分析报告是输出到Debugger(调试器)窗口中的,如下所示:

可以设置成both,这样既会输出到调试器的窗口中,也可以将检测报告输出到文件中。如果ReportTo选项设置为both,还要设置ReportFile选项,指定导出到的文件名称,比如:

还有其他的配置选项,文件中有详细的注解,感兴趣可以去自行试验一下。

6、最后

       也可以使用Windbg中的umdh程序去检测内存泄漏,我们在项目中用过,效果还行。使用umdh检测内存泄漏的详细过程,可以参见我之前写的文章:
使用Windbg定位Windows C++程序中的内存泄漏icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/121295720使用umdh分析时,不用重新编译代码,比较方便。而使用VLD时,需要重新编译代码,会比较麻烦。特别是大型软件,软件中包含了多个dll模块,不同的dll模块是由不同的开发组维护的,让所有模块都用VLD重新编译一下,需要统筹协调,也不是件容易的事。

       另外,这些内存泄漏检测工具不是万能的,没法检测出所有场景下的泄漏。因为大型软件包含了多个模块,代码比较繁琐复杂,有些模块会一上来就会申请内存,一直不释放;有的可能使用到了内存池,内存管理比较复杂。这会导致工具出现误检测,到底是不是真正的内存泄漏点,还要结合具体的代码和业务去分析。一个工具检测不出来,还需要尝试使用其他工具,甚至需要把很多工具都尝试一遍。

       对于分析内存泄漏的工具,若干年前有个强大的工具叫BoundsChecker,但这个工具很久不维护了,新版本的Visual Studio已经没法再使用了。此外,Visual Studio 2019 V19.6版本开始引入了google的内存分析工具AddressSanitizer:

也可以尝试使用AddressSanitizer。对于如何在VS中如何使用AddressSanitizer内存分析工具,可以看一下微软官方文章的详细说明:

在Visual Studio中使用AddressSanitizericon-default.png?t=N7T8https://docs.microsoft.com/zh-cn/cpp/sanitizers/asan?view=msvc-170       要使用Visual Studio中集成的AddressSanitizer,需要将IDE升级到Visual Studio 2019 V19.6或以上版本,要将大型软件从上到下的多个模块统一升级到某个版本,需要一定的时间和人力的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1022866.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二维码生成器

二维码生成器 二维码生成器_二维码在线制作_应用方案提供商_互联二维码 使用方式 先知道自己电脑端口 然后运行你要生成页面 拼接自己的端口和页面路径

四川天蝶电子商务有限公司正规吗?

近年来,随着短视频平台的兴起,抖音成为了中国最受欢迎的社交媒体之一。许多企业看到了抖音带货的巨大商机,纷纷涌入这个领域。然而,一些不法分子也乘机滋生,伪装成合法的商家,进行各种欺诈行为。所以&#…

这些提高摸鱼效率的自动化测试技巧,提高打工人幸福感~

最近有许多小伙伴都在吐槽打工好难。 每天都是执行许多重复的任务 例如阅读新闻、发邮件、查看天气、打开书签、清理文件夹等等, 使用自动化脚本,就无需手动一次又一次地完成这些任务, 非常方便啊有木有?! 今天就…

rv1126-rv1109-瑞芯微的 IPC 程序

关闭瑞芯微的 IPC 程序 例程源码中,第一次下载之后会进入一个类似摄像头demo预览的界面 我想要关掉它,找了很久,终于发现 \rv1126_rv1109\buildroot\board\rockchip\rv1126_rv1109\fs-overlay-sysv\etc\init.d\S98_lunch_init 这个文件注解掉全部 就可以看到注解掉就只有l…

软文推广在医疗行业中的优势有哪些?媒介盒子告诉你

随互联网的快速发展,越来越多的企业开始利用网络宣传,医疗行业也参与其中,相比于传统广告的高成本和不明显的效果,软文推广的效果更明显,对医疗行业的宣传帮助也更大,现在就由媒介盒子告诉大家,…

springboot整合mybatis(详解)

springboot整合mybatis 1. 整体架构展示&#xff1a; 2. pom.xml-需要的依赖&#xff1a; <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency&g…

ICS TRIPLEX T8461 PLC系统备件模块

ICS TRIPLEX T8461 是一款用于 PLC&#xff08;可编程逻辑控制器&#xff09;系统备件的模块&#xff0c;通常用于工业自动化和控制系统中。这种类型的备件模块在多个应用领域都有广泛的用途&#xff0c;包括但不限于以下几个领域&#xff1a; 制造业&#xff1a; T8461 模块可…

FastAdmin开发七牛云上传插件

一看官网一个上传插件60大洋&#xff0c;对我这个穷鬼来说还是太贵了&#xff0c;于是乎自己写一个&#xff0c;后面随时用 直接开干 创建插件 php think addon -a aliupload -c create创建配置 <?phpreturn [[name > region,title > 获取存储区域,type > sel…

Linux内核中断(内核中断实现过程、注册三个按键中断实例、中断底半部实例、工作队列)

一、linux内核中断 1.目的&#xff1a; 用于对设备不用进行轮询访问&#xff0c;而是当设备事件发生后主动通知内核&#xff0c;内核再去访问设备。 2.linux内核中断实现过程框图 3.中断子系统API 1.解析中断相关的设备树节点 struct device_node *of_find_compatible_node…

【笔试强训选择题】Day44.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&#xff…

CSS 滚动驱动动画 scroll-timeline ( scroll-timeline-name ❤️ scroll-timeline-axis )

scroll-timelinescroll-timeline-name❤️scroll-timeline-axis 解决问题语法 animation-timeline-nameanimation-timeline-axis scroll-timeline ( scroll-timeline-name ❤️ scroll-timeline-axis ) 在 scroll() 的最后我们遇到了因为定位问题导致滚动效果失效的情况, 当…

选择渲染农场的几个标准

随着电影、电视剧等影视作品的制作越来越依赖于计算机特效&#xff0c;渲染农场的使用也变得越来越普遍。渲染农场是一种利用大量计算机图形处理器&#xff08;GPU&#xff09;来加速渲染过程的服务。在选择渲染农场时&#xff0c;有几个标准可以帮助您确定哪个农场是适合您的项…

图神经网络系列之消息传递

文章目录 1.前言2.消息传递机制1.RecGNN2.ConvGNNs3.GAT 1.前言 相比较于神经网络最基本的网络结构全连接层&#xff08;MLP&#xff09;&#xff0c;特征矩阵乘以权重矩阵&#xff0c;图神经网络多了一个邻接矩阵。计算形式很简单&#xff0c;三个矩阵相乘再加上一个非线性变…

rv1126-rv1109-编译的剖析

./build.sh uboot:cmds./build.sh ubootcd u-boot make rv1126_defconfig make menuconfig ### 保存配置到对应的⽂件rv1126_defconfig make savedefconfig cp defconfig configs/rv1126_defconfig //剖析 ./build.sh uboot //调用 ./mk-loader.sh build.sh -> mk-all.sh …

软件安全测试为什么重要?安全测试应该怎么进行?

在当前数字化时代&#xff0c;软件已经成为我们生活中不可或缺的一部分&#xff0c;无论是在工作中还是生活中&#xff0c;我们都离不开各种各样的软件。然而&#xff0c;随着软件的普及和应用范围的扩大&#xff0c;软件安全问题也逐渐凸显出来&#xff0c;给企业和个人带来了…

无涯教程-JavaScript - SECH函数

描述 SECH函数返回某个Angular的双曲正割。双曲正割是双曲余弦的倒数。因此,双曲正割的值由等式给出- $$\sinh\left(x\right)\frac {1} {\cosh\left(x\right)} \frac {2} {e ^ x e ^ {-x}} $$ 语法 SECH (number)争论 Argument描述Required/OptionalNumberNumber is the …

Backup: MML shutdown 忽略

RMAN Backup Job is Completed But RMAN Sessions are Not Released in Database When Using Netbackup (Doc ID 2903139.1)​编辑To Bottom In this Document Symptoms Changes Cause Solution APPLIES TO: Oracle Database - Enterprise Edition - Version 19.8.0.0.0 and …

Outlook打开超链接用默认浏览器Microsoft outlook open hyperlink using default browser

这两天outlook打开超链接一直用edge&#xff0c;但我的默认浏览器是chrome。 解决方法 在outlook的选项中的高级设置里面&#xff0c;将超链接打开选为默认浏览器。

「UG/NX」Block UI 指定位置SpecifyLocation

✨博客主页何曾参静谧的博客📌文章专栏「UG/NX」BlockUI集合📚全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C+&#

Navicat中查询指定字段名所在的表名

Navicat中查询指定字段名所在的表名 代码如下&#xff1a; SELECT * FROM information_schema.COLUMNS WHERE COLUMN_NAME替换成你要查找的字段;显示结果如下&#xff1a; 或者这段代码&#xff1a; SELECT table_name, column_name FROM information_schema.columns WHERE c…