使用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或以上版本,要将大型软件从上到下的多个模块统一升级到某个版本,需要一定的时间和人力的。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐几款实用的项目进度管理软件

做好项目的进度管理是项目经理的重要职责,在这个过程中,并非单凭人力就可以把控。项目进度管理软件出现,成为人们在项目管理过程中最需要的工具之一。一个项目无论大小,都需要一款高效且实用的项目管理工具,对项目流程…

actf_2019_babystack

actf_2019_babystack Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x3ff000)64位,只开了nx __int64 __fastcall main(int a1, char **a2, char **a3) {char s[208]; // [rsp0h] [rbp-D…

华为云云耀云服务器L实例评测 |云服务器选购

华为云耀云服务器 L 实例是一款轻量级云服务器,开通选择实例即可立刻使用,不需要用户再对服务器进行基础配置。新用户还有专享优惠,2 核心 2G 内存 3M 带宽的服务器只要 89 元/年,可以点击华为云云耀云服务器 L 实例购买地址去购买…

leetcode25 K个一组反转链表

题目 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部…

计算机网络常见问题

1.谈一谈对OSI七层模型和TCP/IP四层模型的理解? 1.1.为什么要分层? 在计算机中网络是个复杂的系统,不同的网络与网络之间由于协议,设备,软件等各种原因在协调和通讯时容易产生各种各样的问题。例如:各物流…

阿里云大数据实战记录10:Hive 兼容模式的坑

文章目录 1、前言2、什么是 Hive 兼容模式?3、为什么要开启 Hive 模式?4、有什么副作用?5、如何开启 Hive 兼容模式?6、该场景下,能不能不开启 Hive 兼容模式?7、为什么不是DATE_FORMAT(datetime, string)&…

SDXL prompt 笔记

模型 模型有两个,分别是 stable-diffusion-xl-base-1.0、stable-diffusion-xl-refiner-1.0。 base 模型是用来做文生图,refiner 模型是用来做图生图的。 SDXL 模型之 base、refiner 和 VAE_云水木石的博客-CSDN博客 分辨率 默认是1024*1024&#xf…

【MySQL】 MySQL的增删改查(进阶)--贰

文章目录 🛫新增🛬查询🌴聚合查询🚩聚合函数🎈GROUP BY子句📌HAVING 🎋联合查询⚾内连接⚽外连接🧭自连接🏀子查询🎡合并查询 🎨MySQL的增删改查(…

示例-安装office2016图文教程简体中文下载安装包

目录 简介 步骤 总结 简介 Office 2016作为一款办公软件套件,下载和安装 都具有许多令人印象深刻的特点。让我来为你介绍一下:Office 2016注重实现跨平台的一致性。无论你是在Windows、Mac、iOS还是Android上使用Office,你都可以享受到相似…

深入探讨栈数据结构:定义、特性和应用

文章目录 🍋介绍🍋栈的定义🍋栈的实现🍋栈的应用🍋练习题🍋总结 🍋介绍 在计算机科学中,栈(Stack)是一种基本的数据结构,它遵循特定的数据存储和操…

DS相关题目

DS相关题目 题目一:消失的数字 拿到这道题目之后,首先可以想到的一个解题方法就是,我们可以先排序,排完序之后,这个数组其实就是一个有序的数组了,那只用比较数组中的每一个元素和他对应的下标是不是相等的…

火花塞工作原理

1.红旗H9轿车2023款发布 2023年元旦过后,红旗汽车在人民大会堂举办了红旗H9的新车发布会,一汽红旗全新的H9豪华轿车终于出炉了全套的配置参数,红旗H9的车身长度达到5137mm,宽度1904mm,轴距3060mm,总高则控…