阐明

应用 VLD 内存透露检测工具辅助开发时整顿的学习笔记。本篇对 VLD 源码包中的各文件用处做个概述。同系列文章目录可见 《内存透露检测工具》目录

[TOC]

<br/>

1. 整体概览

vld2.5.1 版本为例,下载源码 后,根目录下一共 5 个文件夹:.teamcitylibmfc_detectsetupsrc。还有 12 个文件:.editorconfig.gitignore.mailmapappveyor.ymlAUTHORS.txtchange_toolset.ps1CHANGES.txtCOPYING.txtREADME.mdvld.inivld_vs14.slnvld_vs14_wo_mfc.sln

2. 文件夹 .teamcity

该文件夹的目录构造如下:

vld-master\.teamcity└─Vld    │  project-config.xml    │    ├─buildTypes    │      Vld_CompileAll.xml    │      Vld_DebugCrtDllWin32.xml    │    ├─pluginData    │      plugin-settings.xml    │    └─vcsRoots            Vld_HttpsGithubComKindDragonVldGitRefsHeadsMaster.xml

外面全是 xml 文件,是 teamcity 继续集成工具的配置文件,用于 VLD 我的项目源码的集成治理,对于该工具的介绍,可拜访其官网:Jetbrains-teamcity。

3 文件夹 lib

该文件夹下有三个子文件夹:cppformatdbghelpgtest

3.1 文件夹 cppformat(生成 libformat)

该文件夹的目录构造如下:

vld-master\lib\cppformat    ChangeLog.rst    format.cc    format.h    format.vcxproj    format.vcxproj.filters    LICENSE.rst    posix.cc    posix.h

cppformat 是一个开源的 C++ 格式化库,仓库地址为 Github-fmtlib,在 VLD 中被用来格式化输入堆栈信息,详见 源码 callstack.cpp 第 224~275 行。

3.2 文件夹 dbghelp

该文件夹的目录构造如下:

vld-master\lib\dbghelp├─include│      DbgHelp.h│└─lib    ├─Win32    │      DbgHelp.Lib    │    └─x64            DbgHelp.Lib

dbghelpWindows 零碎下的调试跟踪库,相干信息可见 对于 DbgHelp,在 VLD 中被用来获取堆栈信息,详见源码中 callstack.cpp、vld.cpp、vld_hooks.cpp 等文件。

3.3 文件夹 gtest(生成 libgtest)

该文件夹的目录构造如下:

vld-master\lib\gtest│  CHANGES│  CMakeLists.txt│  configure│  configure.ac│  CONTRIBUTORS│  LICENSE│  Makefile.am│  Makefile.in│  README│├─include│  └─gtest│      │  gtest-death-test.h│      │  gtest-message.h│      │  gtest-param-test.h│      │  gtest-param-test.h.pump│      │  gtest-printers.h│      │  gtest-spi.h│      │  gtest-test-part.h│      │  gtest-typed-test.h│      │  gtest.h│      │  gtest_pred_impl.h│      │  gtest_prod.h│      ││      └─internal│              gtest-death-test-internal.h│              gtest-filepath.h│              gtest-internal.h│              gtest-linked_ptr.h│              gtest-param-util-generated.h│              gtest-param-util-generated.h.pump│              gtest-param-util.h│              gtest-port.h│              gtest-string.h│              gtest-tuple.h│              gtest-tuple.h.pump│              gtest-type-util.h│              gtest-type-util.h.pump│├─msvc│      gtest-md.sln│      gtest.sln│      gtest.vcxproj│      gtest.vcxproj.filters│      gtest_main.vcxproj│      gtest_main.vcxproj.filters│      gtest_prod_test.vcxproj│      gtest_prod_test.vcxproj.filters│      gtest_unittest.vcxproj│      gtest_unittest.vcxproj.filters│└─src        gtest-all.cc        gtest-death-test.cc        gtest-filepath.cc        gtest-internal-inl.h        gtest-port.cc        gtest-printers.cc        gtest-test-part.cc        gtest-typed-test.cc        gtest.cc        gtest_main.cc

gtestGoogle 开源的单元测试框架,仓库地址为 Github-googletest,在 VLD 中被用来测试 VLD 的各个性能,生成测试报告,详见 vld-master\src\tests 文件夹。

4 文件夹 mfc_detect(vld 辅助工程)

该文件夹的目录构造如下:

vld-master\mfc_detect│  resource.h│  StdAfx.cpp│  StdAfx.h│  vldmfc.cpp│  vldmfc.h│  vldmfc.rc│  vldmfc_detect.sln│  vldmfc_detect.vcxproj│  vldmfc_detect.vcxproj.filters│  vldmfc_detect_vs10.sln│  vldmfc_detect_vs11.sln│  vldmfc_detect_vs14.sln│└─res        vldmfc.ico        vldmfc.rc2

这个文件夹中的 sln 解决方案,次要用于获取各版本 mfc.dllnew 函数序号(即 ORDINAL 值),将获取的函数序号用于 VLD 开发,用途详见 源码 dllspatches.cpp 第 88~370 行,获取思路详见 StackOverflow-Getting-ordinal-from-function-name-programmatically,获取时对应的动静库版本及函数详见 文件 vldmfc.cpp 第 189~301 行。这个文件夹下有多个 .sln 文件,它们别离对应不同的 Microsoft Visual Studio 版本,将其用记事本或其余文本编辑器关上,能够晓得对应的版本号:

  • 文件 vldmfc_detect.sln 对应 Visual Studio 2008VC 版本号为 VC9.0
  • 文件 vldmfc_detect_vs10.sln 对应 Visual Studio 2010VC 版本号为 VC10.0
  • 文件 vldmfc_detect_vs11.sln 对应 Visual Studio 2012VC 版本号为 VC11.0
  • 文件 vldmfc_detect_vs14.sln 对应 Visual Studio 2015VC 版本号为 VC14.0

5 文件夹 setup

这个文件夹中的文件次要用来打包 VLD 的安装程序,应用的装置制作软件为 Inno Setup 5.4.2,其官网为:Inno Setup。该文件夹下有两个子文件夹:dbghelpeditenv。以及 6 个文件:build_version.batlicense-free.txtmodpath.issversion.hvld-setup.issWizSmallImage.bmp

5.1 文件夹 dbghelp

该文件夹的目录构造如下:

vld-master\setup\dbghelp├─x64│      dbghelp.dll│      Microsoft.DTfW.DHL.manifest│└─x86        dbghelp.dll        Microsoft.DTfW.DHL.manifest

dbghelp 下存储的是 VLD 依赖的 dbghelp 动静库及对应的清单文件(.manifest 文件),装置 VLD 时会被存储到 VLD 装置目录下(详见 .\Visual Leak Detector\bin)。

5.2 文件夹 editenv

该文件夹的目录构造如下,只有一个 editenv.dll 文件:

vld-master\setup\editenv    editenv.dll

这个库是 Dan Moulding 旧版 VLD 批改环境变量时应用的动静库,详见 StackOverflow-programmatically-adding-a-directory-to-windows-path-environment-variable,对应的仓库为 Github-editenv。KindDragon 新版 VLD 是没有用到这个文件的,应用的是文件 modpath.iss,另一种办法。

5.3 文件 build_version.bat

文件 build_version.bat 是批处理脚本,用于 Inno Setup 疾速打包 VLD 装置器。

5.4 文件 license-free.txt

文件 license-free.txt 是要在 VLD 安装程序中显示的许可信息。

5.5 文件 modpath.iss

文件 modpath.issInno Setup 脚本,采纳 Pascal 编写,用于 VLD 装置时批改 Path 环境变量。

5.6 文件 version.h

文件 version.h 存储 VLD 的版本信息,被 VLD 源码援用,详见 源码 vldint.h 第 40 行。

5.7 文件 vld-setup.iss

文件 vld-setup.issInno Setup 生成的脚本,用于领导生成 VLD 装置器,默认状况下,在装置实现后会生成对应的卸载器 unins000.datunins000.exe,详见 VLD 装置目录。

5.8 文件 WizSmallImage.bmp

文件 WizSmallImage.bmp 是安装程序右上角显示的图像。

6 文件夹 src

这个文件夹用来存储 VLD 库的外围源代码,以及 VLD 功能测试的源代码。有一个 tests 子文件夹及另外 34 个文件。

6.1 内部 34 个文件(vld 外围工程)

34 个文件别离为:

vld-master\src   callstack.cpp   callstack.h   criticalsection.h   crtmfcpatch.h   dbghelp.h   dllspatches.cpp   loaderlock.h   map.h   ntapi.cpp   ntapi.h   resource.h   runalltests.bat   runtests.bat   set.h   stdafx.cpp   stdafx.h   tree.h   utility.cpp   utility.h   vld.cpp   vld.dll.dependency.x64.manifest   vld.dll.dependency.x86.manifest   vld.h   vld.natvis   vld.rc   vld.vcxproj   vld.vcxproj.filters   vldallocator.h   vldapi.cpp   vldheap.cpp   vldheap.h   vldint.h   vld_def.h   vld_hooks.cpp

其中有 17.h 文件、9.cpp 文件,都是 VLD 外围源码的一部分,以下 6 个文件用于 VLD 我的项目配置、依赖库的版本控制等:

vld.natvisvld.rcvld.vcxprojvld.vcxproj.filtersvld.dll.dependency.x64.manifestvld.dll.dependency.x86.manifest

以下两个批处理文件用于 VLD 的性能批量测试,并主动生成测试报告。

runalltests.batruntests.bat

6.2 文件夹 tests

这个文件夹用来存储 VLD 的测试工程代码以及应用示例工程代码,有 14 个子文件夹及另外 2 个文件。

  • Common.propsVS 的属性管理文件,被多个 VLD 测试工程所应用,应用介绍可参考 .vcxproj 和 .props 文件构造。
  • copydlls.bat 是批处理脚本,被用做为 VLD 测试工程的事后生成事件(Pre-Build Event),将 vld.inivld_xx.dllvld_xx.pdbdbghelp.dllMicrosoft.DTfW.DHL.manifest5 个依赖文件复制到指定目录。

6.3 文件夹 tests\basics(测试工程)

该文件夹的目录构造如下:

vld-master\src\tests\basics    Allocs.cpp    Allocs.h    basics.cpp    basics.vcxproj    basics.vcxproj.filters    basics_disabled.cpp    stdafx.cpp    stdafx.h    targetver.h

这是一个 VLD 测试工程,用来测试:当应用不同的内存调配函数(例如 malloccallocplacement new 等)时,VLD 是否正确检测出内存透露。被测的内存调配函数详见 Allocs.h 文件 与 Allocs.cpp 文件。测试用例详见 basics.cpp 文件 与 basics_disabled.cpp 文件。

6.4 文件夹 tests\console(示例工程)

该文件夹的目录构造如下:

vld-master\src\tests\console    main.c    main.cpp    README.md    vldconsole.sln    vldconsole.vcxproj    vldconsole.vcxproj.filters    vldconsole_vs10.sln

这是一个 VLD 示例工程,用来演示如何在一般的控制台程序中应用 VLD 库,演示指标为:VLD 库不仅能检测出 C 程序中 malloc 引起的透露(详见 main.c 文件),也能检测出 C++ 程序中 new 引起的透露(详见 main.cpp 文件)。

  • 文件 vldconsole.sln 对应 Visual Studio 2008VC 版本号为 VC9.0
  • 文件 vldconsole_vs10.sln 对应 Visual Studio 2010VC 版本号为 VC10.0

6.5 文件夹 tests\corruption(测试工程)

该文件夹的目录构造如下:

vld-master\src\tests\corruption    corruption.cpp    corruption.vcxproj    corruption.vcxproj.filters    stdafx.cpp    stdafx.h    targetver.h    Tests.cpp    Tests.h

这是一个 VLD 测试工程,用来测试:当内存调配函数与开释函数不匹配(例如 mallocdelete 配对应用)、调配的堆与开释的堆不匹配时,VLD 是否正确检测出内存透露。被测的失配用法详见 Tests.h 文件 与 Tests.cpp 文件。测试用例详见 corruption.cpp 文件。

6.6 文件夹 tests\dynamic_app(测试工程)

该文件夹的目录构造如下:

vld-master\src\tests\dynamic_app    dynamic_app.cpp    dynamic_app.vcxproj    dynamic_app.vcxproj.filters    LoadTests.cpp    LoadTests.h    stdafx.cpp    stdafx.h    targetver.h    ThreadTest.cpp    ThreadTests.h

这是一个 VLD 测试工程,用来测试:当动静加载一般动静库与 MFC 动静库时,VLDEnableModuleVLDResolveCallstacks 性能是否失常,以及当在多线程中加载动静库时,VLDGetLeaksCount 及透露检测性能是否失常。被测的动静加载用法详见 LoadTests.h 文件 与 LoadTests.cpp 文件,被测的多线程用法详见 ThreadTests.h 文件 与 ThreadTest.cpp 文件。测试用例详见 dynamic_app.cpp 文件。这一测试工程需依赖 dynamic.dlltest_mfc.dll 这两个动静库,它们由 tests 文件夹下的另外两个工程生成。

6.7 文件夹 tests\dynamic_dll(测试辅助工程)

该文件夹的目录构造如下:

vld-master\src\tests\dynamic_dll    dllmain.cpp    dynamic.cpp    dynamic.h    dynamic.vcxproj    dynamic.vcxproj.filters    stdafx.cpp    stdafx.h    targetver.h

这是一个 VLD 测试辅助工程,用来生成动静库 dynamic.dll,而后将生成的动静库给其余测试工程做 VLD 功能测试。库中用三种形式(mallocnewnew[])别离产生 6 处透露,一共 18 处透露,且库源码中未蕴含 vld.h,详见 dynamic.h 文件 与 dynamic.cpp 文件。

6.8 文件夹 tests\mfc(示例工程)

该文件夹的目录构造如下:

vld-master\src\tests\mfc│  resource.h│  StdAfx.cpp│  StdAfx.h│  vldmfc.cpp│  vldmfc.h│  vldmfc.rc│  vldmfc.sln│  vldmfc.vcxproj│  vldmfc.vcxproj.filters│  vldmfcdlg.cpp│  vldmfcdlg.h│  vldmfc_vs10.sln│└─res        vldmfc.ico        vldmfc.rc2

这是一个 VLD 示例工程,用来演示如何在 MFC 程序中应用 VLD 库,演示指标为:VLD 库能检测出 MFC 程序中的内存透露。它通过模态显示一个抉择对话框(详见 vldmfcdlg.h 文件 与 vldmfcdlg.cpp 文件),让用户抉择是否成心产生一个内存透露(详见 vldmfc.h 文件 与 vldmfc.cpp 文件),而后通过查看控制台的 VLD 输入,来演示其内存透露检测性能。

  • 文件 vldmfc.sln 对应 Visual Studio 2008VC 版本号为 VC9.0
  • 文件 vldmfc_vs10.sln 对应 Visual Studio 2010VC 版本号为 VC10.0

6.9 文件夹 tests\mfc_dll(测试辅助工程)

该文件夹的目录构造如下:

vld-master\src\tests\mfc_dll│  mfc.cpp│  mfc.def│  mfc.h│  mfc.rc│  mfc.vcxproj│  mfc.vcxproj.filters│  Resource.h│  stdafx.cpp│  stdafx.h│  targetver.h│└─res        mfc.rc2

这是一个 VLD 测试辅助工程,用来生成动静库 test_mfc.dll,而后将生成的动静库给其余测试工程做 VLD 功能测试。库中用三种形式(newCString initialisation with stringnew[])产生一共 11 处透露,且库源码中未蕴含 vld.h,详见 mfc.cpp 文件。

6.10 文件夹 tests\suite(测试工程)

该文件夹的目录构造如下:

vld-master\src\tests\suite    testsuite.cpp    testsuite.vcxproj    testsuite.vcxproj.filters    testsuite.vcxproj.vspscc

这是一个 VLD 测试工程,只有一个 cpp 文件,用来测试:在多线程(应用 _beginthreadex 创立线程)、多种调配形式(例如 newmallocHeapAlloc 等)、不同递归深度、随机分配内存、随机开释内存时,VLD 是否按需正确检测出内存透露(测试过程中也会随机地配对应用 VLDDisableVLDRestore 疏忽一些透露,详见 testsuite.cpp 第 220~225 行)。

6.11 文件夹 tests\vld_ComTest(测试辅助工程)

该文件夹的目录构造如下:

vld-master\src\tests\vld_ComTest    ComTest.aps    ComTest.cpp    ComTest.def    ComTest.idl    ComTest.rc    ComTest.rgs    ComTest.sln    ComTest_vs14.vcxproj    ComTest_vs14.vcxproj.filters    dlldata.c    dllmain.cpp    dllmain.h    MyMath.cpp    MyMath.h    MyMath.rgs    Resource.h    stdafx.cpp    stdafx.h    targetver.h    xdlldata.c    xdlldata.h

这是一个 VLD 测试辅助工程,用于测试 VLD 是否检测到 COM-based leaks,工程运行后生成了一个 COM 组件 ComTest.dll,源文件 stdafx.h 中有 #include <vld.h>,但其接口函数并没有成心产生内存透露(如下,详见 MyMath.cpp 文件),且在 tests 文件夹下未发现有工程应用了 ComTest.dll

STDMETHODIMP CMyMath::Test(void){    AFX_MANAGE_STATE(AfxGetStaticModuleState());    return S_OK;}

6.12 文件夹 tests\vld_dll1(测试辅助工程)

该文件夹的目录构造如下:

vld-master\src\tests\vld_dll1    dllmain.cpp    stdafx.cpp    stdafx.h    targetver.h    vld_dll1_vs14.vcxproj    vld_dll1_vs14.vcxproj.filters

这是一个 VLD 测试辅助工程,用来生成动静库 vld_dll1.dll,而后将生成的动静库给其余测试工程做 VLD 功能测试,这个库源码中蕴含了 vld.h,且应用了 VLD_FORCE_ENABLE 宏。库中用 malloc 产生 1 处透露,详见 dllmain.cpp 文件。

6.13 文件夹 tests\vld_dll2(测试辅助工程)

该文件夹的目录构造如下:

vld-master\src\tests\vld_dll2    dllmain.cpp    stdafx.cpp    stdafx.h    targetver.h    vld_dll2_vs14.vcxproj    vld_dll2_vs14.vcxproj.filters

这是一个 VLD 测试辅助工程,用来生成动静库 vld_dll2.dll,而后将生成的动静库给其余测试工程做 VLD 功能测试。与 vld_dll1.dll 一样,这个库源码中(stdafx.h 文件)蕴含了 vld.h,且应用了 VLD_FORCE_ENABLE 宏。库中用 malloc 产生 1 处透露,详见 dllmain.cpp 文件。

6.14 文件夹 tests\vld_main(示例工程)

该文件夹的目录构造如下:

vld-master\src\tests\vld_main    stdafx.cpp    stdafx.h    targetver.h    vld_main.cpp    vld_main_vs14.vcxproj    vld_main_vs14.vcxproj.filters

这是一个 VLD 示例工程,工程运行后生成了 vld_main.exe,演示指标为:VLD 能检测出全局动态变量的内存透露,详见 vld_main.cpp 文件。

6.15 文件夹 tests\vld_main_test(测试工程)

该文件夹的目录构造如下:

vld-master\src\tests\vld_main_test    stdafx.cpp    stdafx.h    targetver.h    vld_main_test.cpp    vld_main_test_vs14.vcxproj    vld_main_test_vs14.vcxproj.filters

这是一个 VLD 测试工程,用来测试:VLD 对全局动态变量的透露检测性能是否失常,被测程序为 tests\vld_main 工程生成的 vld_main.exe。测试用例详见 vld_main_test.cpp 文件。

6.16 文件夹 tests\vld_unload(测试工程)

该文件夹的目录构造如下:

vld-master\src\tests\vld_unload    stdafx.cpp    stdafx.h    targetver.h    vld_unload.cpp    vld_unload_vs14.vcxproj    vld_unload_vs14.vcxproj.filters

这是一个 VLD 测试工程,用来测试:主工程未蕴含 vld.h,但多个被调的动静库蕴含 vld.h 时,对各 dll 进行动静装置、动静卸载的状况下,VLD 的透露检测性能是否失常。测试用例详见 vld_unload.cpp 文件。这一测试工程需依赖 vld_dll1.dllvld_dll2.dll 这两个动静库,它们由 tests 文件夹下的另外两个工程生成。

7 其余 12 个文件

源码根目录下还有以下 12 个文件:

vld-master   .editorconfig   .gitignore   .mailmap   appveyor.yml   AUTHORS.txt   CHANGES.txt   change_toolset.ps1   COPYING.txt   README.md   vld.ini   vld_vs14.sln   vld_vs14_wo_mfc.sln

7.1 文件 .editorconfig

这个文件用来对立代码款式,帮忙开发者保护编辑器编码格调,以下几个材料对了解该文件的作用有帮忙:

  • 牧之博客-.editorconfig 文件。
  • Microsoft-应用 EditorConfig 创立可移植的自定义编辑器设置。
  • EditorConfig。

7.2 文件 .gitignore

这个文件用来指明源码上传 Git 时,哪些文件应该被疏忽,这些文件无需纳入 Git 治理。Github-gitignore 上有一些 .gitignore 文件模板,须要时能够拿来用。

7.3 文件 .mailmap

这个文件用于将作者姓名和电子邮件映射到单个标准值,以下几个材料对了解该文件的作用有帮忙:

  • 腾讯云开发者社区-如何应用git .mailmap显示作者组织?。
  • w3cschool-git-check-mailmap。

7.4 文件 appveyor.yml

这个文件用于继续集成服务,主动构建我的项目,以下几个材料对了解该文件的作用有帮忙:

  • appveyor-docs。
  • 51CTO博客-应用Appveyor继续集成博客。

7.5 文件 AUTHORS.txt

这个文件用于列举开发者清单。

7.6 文件 CHANGES.txt

这个文件用于记录版本迭代日志,各版本更新提要。

7.7 文件 change_toolset.ps1

这个文件是一个 PowerShell 脚本,浏览内容可知这个脚本是用来批量更改 Toolset 值的。除 format.vcxprojvld.vcxproj 这两个文件外,它能批改当前目录及其所有子文件夹中的 vcxproj 文件,将文件中的 <PlatformToolset> 值批改为指定值。同时,批改 .\src\tests\Common.props 文件中的 <VldToolset> 值为指定值。对于 <PlatformToolset>,可参考 Microsoft-platform-toolset 以及 对于VS我的项目属性: Target Platform Version 和 Platform ToolSet。

7.8 文件 COPYING.txt

这是一份许可阐明文件,内容是 LGPL 2.1 开源协定。

7.9 文件 README.md

这个文件里对 VLD 的性能用处做了大抵介绍,与 Github-VLD 上的介绍内容一样。

7.10 文件 vld.ini

这个是 VLD 库的配置文件,库的使用者须要用到,应用办法详见自己同系列文章。

7.11 文件 vld_vs14.sln

这个文件是 VLD 我的项目的解决方案文件,需用 Visual Studio 2015 关上,内含 16 个子我的项目,蕴含 VLD 库我的项目、测试项目、示例我的项目,如下图所示:

各项目标简要介绍见下表,能够依据我的项目文件夹名称上翻本文章到介绍处。

标号项目名称对应文件夹名称我的项目简介
1dynamicvld-master\src\tests\dynamic_dll测试用 - 依赖库
2test_mfcvld-master\src\tests\mfc_dll测试用 - 依赖库
3vld_dll1vld-master\src\tests\vld_dll1测试用 - 依赖库
4vld_dll2vld-master\src\tests\vld_dll2测试用 - 依赖库
5libformatvld-master\lib\cppformatVLD - 输入格式化库
6libgtestvld-master\lib\gtest\msvcGoogle Test 测试框架
7ComTestvld-master\src\tests\vld_ComTest测试用-依赖库
8corruptionvld-master\src\tests\corruption库功能测试
9dynamic_appvld-master\src\tests\dynamic_app库功能测试
10test_basicsvld-master\src\tests\basics库功能测试
11testsuitevld-master\src\tests\suite库功能测试
12vld_mainvld-master\src\tests\vld_main用法示例
13vld_main_testvld-master\src\tests\vld_main_test库功能测试
14vld_unloadvld-master\src\tests\vld_unload库功能测试
15vldmfcvld-master\src\tests\mfc用法示例
16vldvld-master\srcVLD - 库

7.12 文件 vld_vs14_wo_mfc.sln

这个文件也是 VLD 我的项目的解决方案文件,需用 Visual Studio 2015 关上,内含 13 个子我的项目,蕴含 VLD 库我的项目、测试项目、示例我的项目,文件名中的 wowithout 的简写,示意没有 MFC 相干的测试项目(除了没有 test_mfcComTestvldmfc 这三个我的项目外,其余中央与 vld_vs14.sln 一样),如下图所示: