说明

使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。


1. 使用前的准备

参考本人另一篇博客
安装 Visual Leak Detector
下载
vld-2.5.1-setup.exe
并按步骤安装 VLD。这一种使用方式的特点是,在一台电脑上安装完成后,将 VLD 安装目录下的 lib 库及 include 文件拷贝到项目目录中,在项目
pro
文件中指明库及头文件的路径,并将
vld.ini
文件和 VLD 安装目录 bin 文件夹下的全部文件拷贝到项目生成目录下,最后在
mian.cpp
文件中
#include "vld.h"
。优点是,当把项目拷贝到别的电脑上编译运行时,该电脑无需安装 VLD,也不需要更改任何代码。

2. 在 QT 中使用 VLD

我的 VLD 安装目录为
D:\Program Files (x86)\Visual Leak Detector
。安装完成后,文件列表如下:

Oh Shit!-图片走丢了-打个广告-欢迎来博客园关注“木三百川”

需要用到的是
bin

include

lib
三个文件夹,以及
vld.ini
文件。下文示例项目所在路径为
E:\Cworkspace\Qt 5.9.0\QtDemo\testVLD
,项目路径下的文件列表如下:

Oh Shit!-图片走丢了-打个广告-欢迎来博客园关注“木三百川”

2.1 复制 lib 库及头文件

拷贝
include
文件夹中的
vld.h

vld_def.h
到项目路径下,拷贝整个
lib
文件夹到项目路径下,这两步拷贝完成后,项目路径下的文件列表如下:

Oh Shit!-图片走丢了-打个广告-欢迎来博客园关注“木三百川”

2.2 在项目 .pro 文件中指明路径

在项目对应的
pro
文件中添加 VLD 的头文件和
lib
库,
pro
文件中添加如下代码:

HEADERS += \
    vld.h \
    vld_def.h

win32{
    CONFIG(debug, debug | release) {
        contains(QT_ARCH, x86_64){
            LIBS += -L$$PWD/lib/Win64 -lvld
        }else{
            LIBS += -L$$PWD/lib/Win32 -lvld
        }
    }
}

2.3 配置 bin 文件夹下的依赖库

拷贝
bin\Win32
文件夹中的四个文件
dbghelp.dll

Microsoft.DTfW.DHL.manifest

vld_x86.dll

vld_x86.pdb
到 32 位 MSVC 在 Debug 模式下的生成目录中,若不使用
DESTDIR
指令,但勾选
Shadow build
,默认的生成路径为
E:\Cworkspace\Qt 5.9.0\QtDemo\build-testVLD-Desktop_Qt_5_9_2_MSVC2015_32bit-Debug\debug
,拷贝结果如下:

Oh Shit!-图片走丢了-打个广告-欢迎来博客园关注“木三百川”

64 位的做类似操作,拷贝
bin\Win64
文件夹中的四个文件
dbghelp.dll

Microsoft.DTfW.DHL.manifest

vld_x64.dll

vld_x64.pdb
到 64 位 MSVC 在 Debug 模式下的生成目录中,若不使用
DESTDIR
指令,但勾选
Shadow build
,默认的生成路径为
E:\Cworkspace\Qt 5.9.0\QtDemo\build-testVLD-Desktop_Qt_5_9_2_MSVC2015_64bit-Debug\debug
,拷贝结果如下:

Oh Shit!-图片走丢了-打个广告-欢迎来博客园关注“木三百川”

更佳的做法是使用
DESTDIR
指令,实现 32 位、64 位在指定路径下生成
exe
,这样可以将
exe
直接生成在对应的
Win32

Win64
路径下,而不需要将上述 4 个文件分别拷贝到对应的
debug
目录

。为实现这种效果,首先将整个
bin
文件拷贝到项目路径下,拷贝完成后,项目路径下的文件列表如下:

Oh Shit!-图片走丢了-打个广告-欢迎来博客园关注“木三百川”

在项目对应的
pro
文件中使用
DESTDIR
指令设置生成路径,添加如下代码:

contains(QT_ARCH, x86_64){
    DESTDIR = $$PWD/bin/Win64
}else{
    DESTDIR = $$PWD/bin/Win32
}

同时,为将
release

debug
两种版本区分出来,不至于在同一个文件夹中引起混乱,在
pro
文件中额为添加如下代码:

TARGET_NAME = testVLD
CONFIG(debug, debug|release) {
    TARGET_NAME = $${TARGET_NAME}-d
}
TARGET = $${TARGET_NAME}

这样设置之后,生成的
debug
版结果将比
release
版结果多一个
-d
后缀,便于区分。

2.4 复制 vld.ini 文件

vld.ini
是 VLD 工具的配置文件,可以修改
vld.ini
内容以定制内存泄漏检测报告。没有该文件其实也能正常运行,但为了后续可定制,最好还是将
vld.ini
拷贝到生成目录下。比如在上一步中的
E:\Cworkspace\Qt 5.9.0\QtDemo\build-testVLD-Desktop_Qt_5_9_2_MSVC2015_32bit-Debug\debug

E:\Cworkspace\Qt 5.9.0\QtDemo\build-testVLD-Desktop_Qt_5_9_2_MSVC2015_64bit-Debug\debug
,若在上一步中使用了
DESTDIR
指令,则生成目录变为
E:\Cworkspace\Qt 5.9.0\QtDemo\testVLD\bin\Win32

E:\Cworkspace\Qt 5.9.0\QtDemo\testVLD\bin\Win64

2.5 在 main.cpp 文件中添加头文件

在项目的
main.cpp
文件中,添加头文件:

#include "vld.h"

选择 MSVC 32bit 或者 MSVC 64bit 编译器,选择
Debug
模式,编译运行,就可以正常使用了。

2.6 无内存泄漏时的输出报告

程序运行结束后,若没有检测到内存泄漏,VLD 会输出以下 4 行报告:

Visual Leak Detector read settings from: E:\Cworkspace\Qt 5.9.0\QtDemo\testVLD\bin\Win32\vld.ini
Visual Leak Detector Version 2.5.1 installed.
No memory leaks detected.
Visual Leak Detector is now exiting.

需要注意的是,此时读取的配置文件
vld.ini
已经不是 VLD 安装路径下的那个了,从第一行可以看到具体路径。使用 64 位 MSVC 时的输出如下:

Visual Leak Detector read settings from: E:\Cworkspace\Qt 5.9.0\QtDemo\testVLD\bin\Win64\vld.ini
Visual Leak Detector Version 2.5.1 installed.
No memory leaks detected.
Visual Leak Detector is now exiting.

因为使用了
DESTDIR
指令, 32 位和 64 位会在所指定的路径下生成,符合预期结果。

3. 无法正常使用的可能原因

按前述步骤进行配置后,就可以卸载已经安装的 VLD 工具了,到 VLD 安装路径下,双击
unins000.exe
,弹窗点击“是(Y)” 按钮卸载 VLD,重新编译运行程序,仍可正常使用。当把项目拷贝到别的电脑上编译运行时,新电脑环境无需安装 VLD,也不需要更改任何代码。若无法正常使用,考虑以下可能的原因。

  • 检查编译器版本
    ,VLD 无法在 minGW 下使用,只能使用 MSVC 编译器。
  • 检查是否是 Debug 模式
    ,VLD 无法直接在 Release 模式下使用。
  • 检查文件的位数是否正确
    ,32 bit /64 bit 不能混用。
  • 清除上一次的编译文件,重新编译运行一下。
  • 若路径中存在空格,添加库时一定要使用
    $$quote()
    将路径括起来,否则路径解析不正确。
  • 检查生成目录下是否包含有 VLD 的 4 个依赖文件,32 位为
    dbghelp.dll

    Microsoft.DTfW.DHL.manifest

    vld_x86.dll

    vld_x86.pdb
    ,64 位为
    dbghelp.dll

    Microsoft.DTfW.DHL.manifest

    vld_x64.dll

    vld_x64.pdb

4. 示例源码

4.1 工程 .pro 文件

# testVLD.pro

QT -= gui

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += main.cpp

HEADERS += \
    vld.h \
    vld_def.h

win32{
    CONFIG(debug, debug | release) {
        contains(QT_ARCH, x86_64){
            LIBS += -L$$PWD/lib/Win64 -lvld
        }else{
            LIBS += -L$$PWD/lib/Win32 -lvld
        }
    }
}

contains(QT_ARCH, x86_64){
    DESTDIR = $$PWD/bin/Win64
}else{
    DESTDIR = $$PWD/bin/Win32
}

TARGET_NAME = testVLD
CONFIG(debug, debug|release) {
    TARGET_NAME = $${TARGET_NAME}-d
}
TARGET = $${TARGET_NAME}

4.2 主函数 main.cpp 文件

// mian.cpp

#include <QCoreApplication>
#include "vld.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    return a.exec();
}

4.3 示例工程目录结构

工程目录结构如下:

E:\Cworkspace\Qt 5.9.0\QtDemo\testVLD
│  main.cpp
│  testVLD.pro
│  testVLD.pro.user
│  vld.h
│  vld_def.h
│
├─bin
│  ├─Win32
│  │      dbghelp.dll
│  │      Microsoft.DTfW.DHL.manifest
│  │      testVLD-d.exe
│  │      testVLD-d.ilk
│  │      testVLD-d.pdb
│  │      testVLD.exe
│  │      testVLD.pdb
│  │      vld.ini
│  │      vld_x86.dll
│  │      vld_x86.pdb
│  │
│  └─Win64
│          dbghelp.dll
│          Microsoft.DTfW.DHL.manifest
│          testVLD-d.exe
│          testVLD-d.ilk
│          testVLD-d.pdb
│          testVLD.exe
│          testVLD.pdb
│          vld.ini
│          vld_x64.dll
│          vld_x64.pdb
│
└─lib
    ├─Win32
    │      vld.lib
    │
    └─Win64
            vld.lib

Oh Shit!-图片走丢了-打个广告-欢迎来博客园关注“木三百川”

标签: none

添加新评论