首页 > 系统相关 >Qt MSVC使用内存泄露检测工具 VLD(Visual Leak Detector)

Qt MSVC使用内存泄露检测工具 VLD(Visual Leak Detector)

时间:2024-03-04 17:26:43浏览次数:29  
标签:exe Qt Leak bytes VLD 内存 testvld 检测工具

一、简介

  VLD = Visual Leak Detector,是一款用于 Visual C++ 的免费的内存泄露检测工具,官网 kinddragon.github.io, GitHub 。先说优点:

  • 为每个泄漏的块提供完整的堆栈跟踪,包括源文件和行号信息(如果可用)。
  • 检测大多数(如果不是全部)类型的进程内内存泄漏,包括基于 COM 的泄漏和纯 Win32 基于堆的泄漏。
  • 可以设置过滤指定的模块(DLL 甚至主 EXE),不参与内存泄露检查。
  • 提供泄漏块的完整数据转储(十六进制和 ASCII)。
  • 可自定义的内存泄漏报告:可以保存到文件或发送到调试器,并且可以包含可变的详细级别
  • 可以设置内存泄露报告的级别
  • 它是一个已经打包的 lib,使用时无须编译它的源代码,只需要引入头文件即可
  • 他的源代码使用 GNU 许可发布,并有详尽的文档及注释。对于想深入了解堆内存管理的读者,是一个不错的选择。

再谈缺点,或者说限制性:

  • 只针对 Visual C++ ,所以 Qt 的项目如果是 MinGW 编译的需要调整为 MSVCXX 构建。
  • 只能检测堆(Heap)上分配的内存泄漏,不能检测资源泄露(如 GDI 等系统资源)。

  总的来说,对于在 Windows 环境下用 VC++ 编译的项目,是免费且十分容易使用的非常棒的内存泄露检查库。可惜目前停留在了 2.5.1 版 (2017-10-17)。

二、下载安装
  https://github.com/KindDragon/vld/releases 下载解压后安装一路点击就可以了。

三、在 Qt 中使用
  使用 VLD 很简单,对于 Qt 项目只需要以下三步即可(假设我们都安装在 D:\VLD 目录下):

  复制头文件、lib文件,将 D:\VLD\下的 include 子目录下的 .h 文件都复制到 Qt 项目对应的构建库目录下对应的 include 、 lib 子目录中。

  构建目录可以通过菜单 工具/选项,Kits中找到项目对应的构建套件(KIT),并找到对应的 qmake.exe所在路径,其父路径就是我们要找的构建库目录,如我这里是 E:\Qt\Qt5.12.2\5.12.2\msvc2017。

  • 源码中引入 vld
  • 包含 vld.h 头文件即可。
  • 修改 .pro 项目文件(这一步,我测试不需要,也许是版本问题?)
1 win32 {
2 CONFIG(debug, debug|release) {
3   # DEFINES += _DEBUG
4   VLD_PATH = C:/Program Files (x86)/Visual Leak Detector
5   INCLUDEPATH += $VLD_PATH/include
6   LIBS += -L$VLD_PATH/lib/Win32 -lvld
7   }
8 }

  如果希望检查 DLL 的内存泄漏,则还要在每个 DLL 的至少一个源文件中包括 vld.h。

  经过如上配置,跑起程序来,如果配置正确,则在【应用程序输出】窗口中,可以看到vld的输出,如下

18:14:33: Debugging starts

Visual Leak Detector read settings from: D:\VLD\vld.ini

Visual Leak Detector Version 2.5.1 installed.

  退出程序,则在【应用程序输出】窗口中看到输出,如下

No memory leaks detected.

Visual Leak Detector is now exiting.

18:14:40: Debugging has finished

  很好,没有泄露,让我们刻意制造一个泄露:

1     int * p = new int();
2     *p = 0xAABBFF;
3  
4     qDebug() << "p address : " << p;

  new 一个 int 型指针,赋值为 0xAABBFF,最后显示指针地址。测试下 VLD 是否能捕获到这个泄露,进一步,是否能显示泄露内存的数据。

  跑起来程序后关闭窗口退出, VLD 显示如下,对关键数据用红色粗斜体标注,并配了#序号: 

#1 p address : 0x40b95a8
WARNING: Visual Leak Detector detected memory leaks!
#2 ---------- Block 8 at 0x040B95A8: 4 bytes ----------
#3 Leak Hash: 0xF4DB2A55, Count: 1, Total 4 bytes
Call Stack (TID 11204):
ucrtbased.dll!malloc()
d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\heap\new_scalar.cpp (35): testvld.exe!operator new() + 0x9 bytes
e:\test\qt\vld\testvld\mainwindow.cpp (19): testvld.exe!MainWindow::MainWindow() + 0x10 bytes
#4 e:\test\qt\vld\testvld\main.cpp (7): testvld.exe!main() + 0xA bytes
c:\users\qt\work\qt\qtbase\src\winmain\qtmain_win.cpp (97): testvld.exe!WinMain() + 0xD bytes
d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (107): testvld.exe!invoke_main()
d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (288): testvld.exe!__scrt_common_main_seh() + 0x5 bytes
d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (331): testvld.exe!__scrt_common_main()
d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_winmain.cpp (17): testvld.exe!WinMainCRTStartup()
KERNEL32.DLL!BaseThreadInitThunk() + 0x19 bytes
ntdll.dll!RtlGetAppContainerNamedObjectPath() + 0x11E bytes
ntdll.dll!RtlGetAppContainerNamedObjectPath() + 0xEE bytes
#5 Data:
FF BB AA 00 ........ ........

Visual Leak Detector detected 1 memory leak (40 bytes).
Largest number used: 498 bytes.
Total allocations: 498 bytes.
Visual Leak Detector is now exiting.
10:21:38: Debugging has finished

#1 是我们程序中输出的地址0x40b95a8 和 VLD 检测到的(#2 Block 8 at 0x040B95A8: 4 bytes)地址一致,并且指出了数据长度为 4 字节。

#4 给出了产生泄露代码文件地址及(e:\test\qt\vld\testvld\main.cpp)、行号(7)及所在函数(testvld.exe!main())

#5 显示出泄露的内存数据片段,正是我们赋值的 0xAABBFF,只是大小端问题,显示为 FF BB AA 00 。

可见,VLD可以非常明确的捕获内存泄露并指出相关的具体信息。

上面是使用 Debug 版输出的情况,接下来看

Release版本如何使用?

在工程设置里加上 VLD_FORCE_ENABLE 预定义宏内存监控才会生效。

1 #define VLD_FORCE_ENABLE
2 #include "vld/vld.h"

相比 Debug 版,Release 版的信息少了很多

p address : 0xba1fa0

WARNING: Visual Leak Detector detected memory leaks!

---------- Block 8 at 0x00BA1FA0: 4 bytes ----------

Leak Hash: 0x25F7E302, Count: 1, Total 4 bytes

Call Stack (TID 544):

ucrtbase.dll!malloc()

testvld.exe!0x0098185C()

testvld.exe!0x00981107()

testvld.exe!0x0098105C()

testvld.exe!0x009826D5()

Data:

FF BB AA 00 ........ ........

Visual Leak Detector detected 1 memory leak (4 bytes).

Largest number used: 214 bytes.

Total allocations: 214 bytes.

Visual Leak Detector is now exiting.

10:57:20: Debugging has finished

  对比两份输出,缺少的部分是函数调用堆栈,也就是说在 release 版中无法获取内存泄露代码的文件路径、行号、调用函数信息。

  但因为提供了内存地址、内存数据片段及大小,对问题的排查帮助还是很大的。

四、在 MSVC++ 中使用

  和 Qt 环境的主要区别就是路径的配置方式不同,以 VS2017为例,在项目右键属性中配置如下

   配置头文件查找目录

  配置 lib 目录

  配置好后,还需要在 VLD 安装目录下 bin 下对应的平台调试文件复制到程序所在目录,如

五、配置内存泄露报告

  VLD 的内存泄露报告是可以定制的,详细的配置描述请参考 Configuration Options · KindDragon/vld Wiki · GitHub

  安装目录下的vld.ini 为默认全局配置,也可以为每个程序单独配置,在应用程序目录下放置vld.ini文件即可。常用的选项如下:

VLD:选择VLD的打开与关闭。在Debug模式下运行,关闭以后会有一行VLD关闭的提示信息。默认为 on。

AggregateDuplicates:设置为 yes 时,相同地方产生内存泄漏只输出一次,但是会统计发生的次数。默认是 no 。

ReportEncoding :report 文件的编码格式,可选有 ascii, unicode,默认是 ascii 。

ReportFile :report 文件的路径。默认是 “.\memory_leak_report.txt”

ReportTo :可选有 debugger, file, both,debugger 表示输出到 debug模式下的输出窗口;file 表示只输出到文件中; both顾名思义,全都都输出。默认是 debugger 。

标签:exe,Qt,Leak,bytes,VLD,内存,testvld,检测工具
From: https://www.cnblogs.com/ybqjymy/p/18052176

相关文章

  • Visual Leak Detector 安装 VLD
    一.工具下载VisualLeakDetector官网下载地址:https://kinddragon.github.io/vld/,点击DownloadInstaller绿色按钮可下载工具的安装程序vld-2.5.1-setup.exe。也可去Git仓库releases界面下载安装程序vld-2.5.1-setup.exe。二.工具安装2.1Next2.2Iacceptt......
  • Visual Studio 打开Qt项目
    一、下载QTVSTOOL插件1.1下载地址官方下载地址:Indexof/development_releases/vsaddin找到对应的VS版本下载1.2 安装先关闭VS,然后安装,在打开VS,就看到顶部有QTVSTOOLS 了1.3 添加路径QtOptions->Add->apth,找到你Qt安装的目录对应的如下文件夹Q......
  • Visual Leak Detector 简介
    1.工具简介VisualLeakDetector简称VLD,是Windows平台下用于C/C++代码内存泄漏检测的开源工具,使用起来比较简单,配置好环境后包含头文件,就可以在运行时自动检测是否存在内存泄漏,并在指定位置(控制台或者文本文件)输出检测报告。该工具最初由DanMoulding开发,但是后面2.......
  • 调整window下qt界面的缩放比例为自适应
    原因:QtCreator的缩放策略是四舍五入,只能缩放到1或2,而不是1.5,就比如系统缩放为150%,qt界面则会被缩放为200%解决办法:Linux下:exportQT_SCALE_FACTOR_ROUNDING_POLICY=PassThrough1.这行代码是环境变量设置的一部分,用于指定QT应用程序的缩放因子舍入策略。QT_SCALE_FACTOR......
  • QT安装指导
    Qt是一个跨平台的 C++ 开发库,主要用来开发图形用户界面(GraphicalUserInterface,GUI)程序。QT有自带的编辑器QtCreator,但是我主要是C#开发者,习惯于使用VS,所以后面会使用VS开发QT。安装包下载地址:https://download.qt.io/archive/online_installers/我使用了最新版本 安装......
  • Qt表格排序例子
    表格排序是Qt内建支持的,用起来很简单。只需要在QtCreator界面给QTableView或QTableWidget的SortingEnabled属性设置为true就行了。本文将对这两种控件分别展示一下效果和一个自定义的排序例子。一、QTableWidget这个不需要任何代码,只需要设计界面时候启用排序就行了。下面直接......
  • Qt/C++音视频开发67-保存裸流加入sps/pps信息/支持264/265裸流/转码保存/拉流推流
    一、前言音视频组件除了支持保存MP4文件外,同时还支持保存裸流即264/265文件,以及解码后最原始的yuv文件。在实际使用过程中,会发现部分视频文件保存的裸流文件,并不能直接用播放器播放,查阅资料得知原来是缺少sps/pps信息,监控行业的rtsp/rtmp/录像mp4文件都是会带的,所以很少遇到这个......
  • pyqt5中多线程爬虫
       设立爬虫Class,继承pyqt5中的Thread函数中使用普通线程  整体代码:importsysimportpandasaspdimportjson,requests,time,threadingfromPyQt5.QtWidgetsimportQMainWindow,QApplication,QVBoxLayout,QMessageBoxfromui.ui_testimportUi_MainWind......
  • QTabWidget的高度取决于当前选项卡的高度
    QTabWidget的高度自适应当前选项卡的高度,可以通过设置其他选项卡的QSizePolicy为Ignored,connect(ui->tabWidget,SIGNAL(currentChanged(int)),this,SLOT(updateSizes(int)));voidMainWindow::updateSizes(intindex){for(inti=0;i<ui->tabWidget->count();i++)......
  • PyQt入门教程(版本1)
    第1章PyQt5开发环境搭建和配置PyQt5工具可以快速实现简单的界面开发,包括界面设计、布局管理以及业务逻辑实现(信号与槽)。简单说就是使用PyQt5工具可以快速画一个控件摆放整齐、界面整洁有序、布局合理的界面。本文内容本文主要第1节PyQt5环境搭建和配置。主要内容包括:[!TIP......