当前位置: 首页 > news >正文

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

目录

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,是不是要把目录下的其他文件也拷贝过去?
于是手动又将bin目录下的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或以上版本,要将大型软件从上到下的多个模块统一升级到某个版本,需要一定的时间和人力的。

相关文章:

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

目录 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、启动调试,查看内存泄漏报…...

如何设计一个 JVM 语言下的 LLM 应用开发框架?以 Chocolate Factory 为例

本文将介绍 Chocolate Factory 框架背后的一系列想法和思路。在我们探索和设计框架的过程中,受到了:LangChain4j、LangChain、LlamaIndex、Spring AI、Semantic Kernel、PromptFlow 的大量启发。 欢迎一起来探索:https://github.com/unit-mes…...

基础排序算法

插入排序(insertion sort) 插入排序每次循环将一个元素放置在适当的位置。像抓牌一样。手里的排是有序的,新拿一张牌,与手里的牌进行比较将其放在合适的位置。 插入排序要将待排序的数据分成两部分,一部分有序&#…...

Nginx的反向代理、动静分离、负载均衡

反向代理 反向代理是一种常见的网络技术,它可以将客户端的请求转发到服务器群集中的一个或多个后端服务器上进行处理,并将响应结果返回给客户端。反向代理技术通常用于提高网站的可伸缩性和可用性,并且可以隐藏真实的后端服务器地址。 #user…...

LLM-TAP随笔——大语言模型基础【深度学习】【PyTorch】【LLM】

文章目录 2.大语言模型基础2.1、编码器和解码器架构2.2、注意力机制2.2.1、注意力机制(Attention)2.2.2、自注意力机制(Self-attention)2.2.3、多头自注意力(Multi-headed Self-attention) 2.3、transforme…...

蓝桥杯备赛-上学迟到

上学迟到 P5707 【深基2.例12】上学迟到 - 洛谷 |https://www.luogu.com.cn/problem/P5707 题目介绍 题目描述 学校和 yyy 的家之间的距离为 s 米,而 yyy 以v 米每分钟的速度匀速走向学校。 在上学的路上,yyy 还要额外花费 1010 分钟的时间进行垃圾分…...

基于 MATLAB 的电力系统动态分析研究【IEEE9、IEEE68系节点】

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

2023百度之星 题目详解 公园+糖果促销

2023百度之星题目详解 文章目录 2023百度之星题目详解前言公园问题题目详解 夏日漫步问题问题详情题目详解 前言 这里为大家带来最新的2023百度之星的题目详解,后续还会继续更新,喜欢的小伙伴可以点个关注啦! 公园问题 今天是六一节&#…...

C++ 2019-2022 CSP_J 复赛试题横向维度分析(中)

上文讲解了2019~2022年第一题和第二题。第一题偏数学认知,算法较简单,第二题考查基本数据结构,如队列、栈……和基础算法,如排序、模拟……。 本文继续讲解第三题和第四题。 1. 第三题 1.1 2022 题目: 逻辑表达式…...

基于Spring Boot的IT技术交流和分享平台的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 我国科学技术的不断发展,计算机的应用日渐成熟,其强大的功能给人们留下深刻的印象,它已经应用到了人类社会的各个层次的领域&#x…...

智算引领·创新未来 | 2023紫光展锐泛物联网终端生态论坛成功举办

9月21日,紫光展锐在深圳成功举办2023泛物联网终端生态论坛。论坛以“智算引领创新未来”为主题,吸引了来自信通院、中国联通、中国移动、中国电信、金融机构、终端厂商、模组厂商等行业各领域三百多位精英翘楚汇聚一堂,探讨在连接、算力驱动下…...

网络安全技术指南 103.91.209.X

网络安全技术指的是一系列防范网络攻击、保护网络安全的技术手段和措施,旨在保护网络的机密性、完整性和可用性。常见的网络安全技术包括: 防火墙:用于监控网络流量,过滤掉可能包括恶意软件的数据包。 加密技术:用于保…...

用flex实现grid布局

1. css代码 .flexColumn(columns, gutterSize) {display: flex;flex-flow: row wrap;margin: calc(gutterSize / -2);> div {flex: 0 0 calc(100% / columns);padding: calc(gutterSize / 2);box-sizing: border-box;} }2.用法 .grid-show-item3 {width: 100%;display: fl…...

东郊到家app小程序公众号软件开发预约同城服务系统成品源码部署

东郊到家app系统开发,东郊到家软件定制开发,东郊到家小程序APP开发,东郊到家源码定制开发,东郊到家模式系统定制开发 一、上门软件介绍 1、上门app是一家以推拿为主项,个人定制型的o2o平台,上门app平台提…...

kotlin的集合使用maxBy函数报NoSuchElementException

kotlin设定函数 fun test() {listOf<Int>().maxBy { it } } 查看java实现...

Python开发与应用实验2 | Python基础语法应用

*本文是博主对学校专业课Python各种实验的再整理与详解&#xff0c;除了代码部分和解析部分&#xff0c;一些题目还增加了拓展部分&#xff08;⭐&#xff09;。拓展部分不是实验报告中原有的内容&#xff0c;而是博主本人自己的补充&#xff0c;以方便大家额外学习、参考。 &a…...

网络安全--防火墙旁挂部署方式和高可靠性技术

目录 一、防火墙 二、防火墙旁挂部署方式 使用策略路由实现 第一步、IP地址配置 第二步、配置路由 第三步、在防火墙上做策略 第四步、在R2上使用策略路由引流 三、防火墙高可靠性技术--HRP 拓扑图 第一步、配置SW1、SW2、FW1、FW2 第二步、进入防火墙Web页面进行配…...

c++最小步数模型(魔板)

C 最小步数模型通常用于寻找两个点之间的最短路径或最少步数。以下是一个基本的 C 最小步数模型的示例代码&#xff1a; #include<bits/stdc.h> using namespace std; const int N 1e5 5; vector<int> G[N]; int d[N]; bool vis[N];void bfs(int s) {queue<i…...

【每日一题Day337】LC460LFU 缓存 | 双链表+哈希表

LFU 缓存【LC460】 请你为 最不经常使用&#xff08;LFU&#xff09;缓存算法设计并实现数据结构。 实现 LFUCache 类&#xff1a; LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象int get(int key) - 如果键 key 存在于缓存中&#xff0c;则获取键的值&#x…...

解决老版本Oracle VirtualBox 此应用无法在此设备上运行问题

问题现象 安装华为eNSP模拟器的时候&#xff0c;对应的Oracle VirtualBox-5.2.26安装的时候提示兼容性问题&#xff0c;无法进行安装&#xff0c;具体版本信息如下&#xff1a; 软件对应版本备注Windows 11专业工作站版22H222621eNSP1.3.00.100 V100R003C00 SPC100终结正式版…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天&#xff0c;深度学习与大模型技术已成为推动行业变革的核心驱动力&#xff0c;而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心&#xff0c;系统性地呈现了两部深度技术著作的精华&#xff1a;…...