Visual Leak Detector使用注意事项

Posted 木三百川

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Visual Leak Detector使用注意事项相关的知识,希望对你有一定的参考价值。

使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇介绍使用 VLD 时的注意事项。

说明

使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇介绍使用 VLD 时的注意事项。同系列文章目录可见 《内存泄漏检测工具》目录


1. 官网文档

可以在 Using-Visual-Leak-Detector 官方文档里看到如何使用 VLD。

2. 注意事项

v2.5.1 版本为例,使用时有以下几点需注意。

  • 只要在项目的其中一个文件中 #include "vld.h" 就够了,这个文件可以是 main 函数所在文件,也可以是其他依赖源码所在文件。多个文件包含其实也没什么影响,但可能不便于后期的代码维护。
  • 一般情况下,只要确保头文件 vld.h 是在预编译头文件(最典型的比如 stdafx.h)之后包含即可,相对于其他头文件来说,include 的顺序没什么影响。但当 stdafx.h 文件中有 #include <afxwin.h> 时,就需将 #include "vld.h" 放在 stdafx.h 文件里面,且要放在 #include <afxwin.h> 的前面,不然泄漏检测功能无法正常使用。
  • 如果要检测某个 DLL 动态链接库是否有内存泄露,最好的方法是在该 DLL 的源代码里面包含 vld.h 后重新打包,然后使用新生成的 DLL 库。另一种方法是修改配置文件 vld.ini 文件中的配置项 ForceIncludeModules,将要检测的 DLL 库名称写在等号右边,具体操作可见本人另一篇博客 配置项 ForceIncludeModules,但根据配置文件中的相关注释,ForceIncludeModules 功能开启后程序有崩溃的风险,因此第二种方法需慎用。

Visual Leak Detector配置项 SkipHeapFreeLeaks

使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇介绍 VLD 配置文件中配置项 SkipHeapFreeLeaks 的使用方法。

说明

使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇介绍 VLD 配置文件中配置项 SkipHeapFreeLeaks 的使用方法。同系列文章目录可见 《内存泄漏检测工具》目录


1. 配置文件使用说明

在程序中通过 #include "vld.h" 的方式检测内存泄漏时,VLD 首先会尝试在程序的生成目录下读取 vld.ini 文件,若未读取成功,则会尝试在 VLD 的安装目录下读取 vld.ini 文件,若仍未读取成功,则会使用内置的默认配置,内置的默认配置如果不动源码是无法更改的,因此通过修改相应目录下的 vld.ini 文件来定制 VLD 功能是最好的选择。当配置参数等号右边为空,或者给配置了不合法值时,在使用过程中会被程序重置到默认值。

2. 设置是否跳过堆内存泄漏检测

参数名SkipHeapFreeLeaks

有效赋值yesno

默认值no

功能说明文档原话Determines whether or not report memory leaks when missing HeapFree calls. 但是当我把这个变量设置为 yes 时仍可以检测到堆上的内存泄漏,这个配置项的实际作用有待进一步研究。

2.1 测试代码

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

void testFun(int i)

    int *ptr = new int(i);
    printf("ptr = %08x, *ptr = %08x.\\n", ptr, *ptr);

    int *pData= (int *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(int));
    printf("pData = %08x, *pData = %08x.\\n", pData, *pData);


int main(int argc, char *argv[])

    QCoreApplication a(argc, argv);

    testFun(1);

    return a.exec();

测试环境:QT 5.9.2MSVC 2015 32bitDebug 模式,VLD 版本为 2.5.1,VLD 配置文件只对该参数做修改,测试工程所在路径为:E:\\Cworkspace\\Qt 5.9\\QtDemo\\testVLD

2.2 SkipHeapFreeLeaks = no 时的输出

标准输出窗显示:

ptr = 00539498, *ptr = 00000001.
pData = 00535720, *pData = 00000000.

VLD 输出报告:

Visual Leak Detector read settings from: D:\\Program Files (x86)\\Visual Leak Detector\\vld.ini
Visual Leak Detector Version 2.5.1 installed.
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 2 at 0x00535720: 4 bytes ----------
  Leak Hash: 0x426C3DE0, Count: 1, Total 4 bytes
  Call Stack (TID 30052):
    ntdll.dll!RtlAllocateHeap()
    e:\\cworkspace\\qt 5.9\\qtdemo\\testvld\\main.cpp (10): testVLD.exe!testFun() + 0x11 bytes
    e:\\cworkspace\\qt 5.9\\qtdemo\\testvld\\main.cpp (18): testVLD.exe!main() + 0x7 bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (74): testVLD.exe!invoke_main() + 0x1B bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (264): testVLD.exe!__scrt_common_main_seh() + 0x5 bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (309): testVLD.exe!__scrt_common_main()
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_main.cpp (17): testVLD.exe!mainCRTStartup()
    KERNEL32.DLL!BaseThreadInitThunk() + 0x19 bytes
    ntdll.dll!RtlGetAppContainerNamedObjectPath() + 0x11E bytes
    ntdll.dll!RtlGetAppContainerNamedObjectPath() + 0xEE bytes
  Data:
    00 00 00 00                                                  ........ ........


---------- Block 1 at 0x00539498: 4 bytes ----------
  Leak Hash: 0x19BB156F, Count: 1, Total 4 bytes
  Call Stack (TID 30052):
    ucrtbased.dll!malloc()
    f:\\dd\\vctools\\crt\\vcstartup\\src\\heap\\new_scalar.cpp (19): testVLD.exe!operator new() + 0x9 bytes
    e:\\cworkspace\\qt 5.9\\qtdemo\\testvld\\main.cpp (7): testVLD.exe!testFun() + 0x7 bytes
    e:\\cworkspace\\qt 5.9\\qtdemo\\testvld\\main.cpp (18): testVLD.exe!main() + 0x7 bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (74): testVLD.exe!invoke_main() + 0x1B bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (264): testVLD.exe!__scrt_common_main_seh() + 0x5 bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (309): testVLD.exe!__scrt_common_main()
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_main.cpp (17): testVLD.exe!mainCRTStartup()
    KERNEL32.DLL!BaseThreadInitThunk() + 0x19 bytes
    ntdll.dll!RtlGetAppContainerNamedObjectPath() + 0x11E bytes
    ntdll.dll!RtlGetAppContainerNamedObjectPath() + 0xEE bytes
  Data:
    01 00 00 00                                                  ........ ........


Visual Leak Detector detected 2 memory leaks (44 bytes).
Largest number used: 44 bytes.
Total allocations: 44 bytes.
Visual Leak Detector is now exiting.

2.3 SkipHeapFreeLeaks = yes 时的输出

标准输出窗显示:

ptr = 014e9450, *ptr = 00000001.
pData = 014e84b0, *pData = 00000000.

VLD 输出报告:

Visual Leak Detector read settings from: D:\\Program Files (x86)\\Visual Leak Detector\\vld.ini
Visual Leak Detector Version 2.5.1 installed.
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 2 at 0x014E84B0: 4 bytes ----------
  Leak Hash: 0x7C37FF93, Count: 1, Total 4 bytes
  Call Stack (TID 7564):
    ntdll.dll!RtlAllocateHeap()
    e:\\cworkspace\\qt 5.9\\qtdemo\\testvld\\main.cpp (10): testVLD.exe!testFun() + 0x11 bytes
    e:\\cworkspace\\qt 5.9\\qtdemo\\testvld\\main.cpp (18): testVLD.exe!main() + 0x7 bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (74): testVLD.exe!invoke_main() + 0x1B bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (264): testVLD.exe!__scrt_common_main_seh() + 0x5 bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (309): testVLD.exe!__scrt_common_main()
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_main.cpp (17): testVLD.exe!mainCRTStartup()
    KERNEL32.DLL!BaseThreadInitThunk() + 0x19 bytes
    ntdll.dll!RtlGetAppContainerNamedObjectPath() + 0x11E bytes
    ntdll.dll!RtlGetAppContainerNamedObjectPath() + 0xEE bytes
  Data:
    00 00 00 00                                                  ........ ........


---------- Block 1 at 0x014E9450: 4 bytes ----------
  Leak Hash: 0x8876C556, Count: 1, Total 4 bytes
  Call Stack (TID 7564):
    ucrtbased.dll!malloc()
    f:\\dd\\vctools\\crt\\vcstartup\\src\\heap\\new_scalar.cpp (19): testVLD.exe!operator new() + 0x9 bytes
    e:\\cworkspace\\qt 5.9\\qtdemo\\testvld\\main.cpp (7): testVLD.exe!testFun() + 0x7 bytes
    e:\\cworkspace\\qt 5.9\\qtdemo\\testvld\\main.cpp (18): testVLD.exe!main() + 0x7 bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (74): testVLD.exe!invoke_main() + 0x1B bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (264): testVLD.exe!__scrt_common_main_seh() + 0x5 bytes
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_common.inl (309): testVLD.exe!__scrt_common_main()
    f:\\dd\\vctools\\crt\\vcstartup\\src\\startup\\exe_main.cpp (17): testVLD.exe!mainCRTStartup()
    KERNEL32.DLL!BaseThreadInitThunk() + 0x19 bytes
    ntdll.dll!RtlGetAppContainerNamedObjectPath() + 0x11E bytes
    ntdll.dll!RtlGetAppContainerNamedObjectPath() + 0xEE bytes
  Data:
    01 00 00 00                                                  ........ ........


Visual Leak Detector detected 2 memory leaks (44 bytes).
Largest number used: 44 bytes.
Total allocations: 44 bytes.
Visual Leak Detector is now exiting.

2.4 输出结果对比

SkipHeapFreeLeaks = noSkipHeapFreeLeaks = yes 的输出结果似乎没有什么实质性的差异,不过有一点需注意,使用 new 分配堆内存时,会额外添加 36 bytes 大小的内存用于追踪管理,但使用 HeapAlloc() 函数分配堆内存时,则没有额外的内存使用,因此上述测试例的 Total allocations44 bytes,而不是 80 bytes

以上是关于Visual Leak Detector使用注意事项的主要内容,如果未能解决你的问题,请参考以下文章

Visual Leak Detector配置项 AggregateDuplicates

Visual Leak Detector配置项 StackWalkMethod

Visual Leak Detector配置项 SkipCrtStartupLeaks

Visual Leak Detector配置项 TraceInternalFrames

Visual Leak Detector配置项 ReportEncoding

Visual Leak Detector配置项 SkipHeapFreeLeaks