首页IT科技visual recoil(让Visual Leak Detector使用最新10.0版本的dbghelp.dll)

visual recoil(让Visual Leak Detector使用最新10.0版本的dbghelp.dll)

时间2025-06-15 09:16:31分类IT科技浏览5294
导读:让Visual Leak Detector使用最新10.0版本的dbghelp.dll 介绍...

让Visual Leak Detector使用最新10.0版本的dbghelp.dll

介绍

VLD(Visual Leak Detector)是一个检测Windows C++程序内存泄漏的老牌神器              ,但好几年没维护了              。

网址:https://github.com/KindDragon/vld/

需求

这个工具通过SxS manifest绑定了只能使用它工程目录下自带的dbghelp.dll来处理pdb符号                      ,版本是6.11.1.404                      。

这个版本目前比较老了       ,所以在解析VS2019/VS2022生成的pdb文件时              ,有时候会崩掉或者无法解析出调用栈的符号                      ,导致无法报出来完整的内存泄漏       ,影响基本功能       。所以需要升级它所使用的dbghelp.dll              。

VLD的实现机制

在首次进入vld_x64.dll的PE入口时       ,inline hook掉ntdll.dll的LdrpCallInitRoutine()函数                      ,因为此时可以假定vld_x64.dll是被ntdll.dll的LdrpCallInitRoutine()函数调用的                      。

这样后续ntdll.dll调用当前进程中的任何dll的入口函数时              ,都会先调用vld_x64.dll提供的一个LdrpCallInitRoutine() hook函数       。

完成hook后       ,会执行vld_x64.dll中的各个全局对象的构造       。vld_x64.dll提供了一个全局对象g_vld                      ,这个对象的构造函数会调用dbghelp.dll的SymInitializeW()来初始化MS的符号库函数                      。

在LdrpCallInitRoutine() hook函数中              ,VLD会刷新当前进程所加载的模块列表,调用dbghelp.dll的SymLoadModuleExW()加载新dll的pdb符号              。

BOOLEAN WINAPI LdrpCallInitRoutine(IN PVOID BaseAddress, IN ULONG Reason, IN PVOID Context, IN PDLL_INIT_ROUTINE EntryPoint) { LoaderLock ll; if (Reason == DLL_PROCESS_ATTACH) { g_vld.RefreshModules(); } return EntryPoint(BaseAddress, Reason, (PCONTEXT)Context); }

问题

这样看起来并无问题       。但是10.0版本的dbghelp.dll相比6.11版本有一个改动                      ,导致VLD现有的pdb符号解析功能失败                      。

那就是10.0版本的SymInitializeW()的内部代码会去加载某些DLL                      ,这会导致走到LdrpCallInitRoutine() hook函数中去刷新模块列表,并最终调用SymLoadModuleExW()              。

也就是说SymInitializeW()在成功返回之前会去调用SymLoadModuleExW()              ,这显然不符合MS的debug help API的约定                      ,所以此时的SymLoadModuleExW()都会返回失败       ,导致汇报泄漏时无法解析符号。

解决办法

1              、设置一个全局的bool标志变量              ,在调用SymInitializeW()之前置位                      ,调用完SymInitializeW()之后清除                      。

dbghelp.h:
extern volatile bool init; BOOL SymInitializeW(_In_ HANDLE hProcess, _In_opt_ PCWSTR UserSearchPath, _In_ BOOL fInvadeProcess) { init = true; CriticalSectionLocker<CriticalSection> cs(m_lock); const auto r = ::SymInitializeW(hProcess, UserSearchPath, fInvadeProcess); init = false; return r; }

2                      、在LdrpCallInitRoutine() hook函数中判断一下       ,如果标志被置位       ,则本次就不要刷新模块列表了                      ,也就不会去调用SymLoadModuleExW()                      。

vld.cpp:
volatile bool init = false; BOOLEAN WINAPI LdrpCallInitRoutine(IN PVOID BaseAddress, IN ULONG Reason, IN PVOID Context, IN PDLL_INIT_ROUTINE EntryPoint) { LoaderLock ll; if (Reason == DLL_PROCESS_ATTACH) { if (!init) g_vld.RefreshModules(); } return EntryPoint(BaseAddress, Reason, (PCONTEXT)Context); }

3       、相应地              ,要删掉VLD工程属性中添加的和SxS有关的设置       ,如

vld.dll.dependency.x64.manifest vld.dll.dependency.x86.manifest dbghelp.dll (6.11版本的) Microsoft.DTfW.DHL.manifest (6.11版本的) $(SolutionDir)\lib\dbghelp\lib\$(PlatformName) (不要依赖这个目录下的lib)

这样编译出来的vld_x64.dll默认会加载system32下的dbghelp.dll。

也可以复制Windows SDK              、VS2019/VS2022                      、windbg目录下的dbghelp.dll                      ,但不要忘了也复制同目录下的那一堆api-ms-win-crt-runtime-l1-1-0.dll之类的CRT dll              。

附赠

几个防止内存泄漏的tips:

1       、静态链接到openssl时              ,需要在DLL_THREAD_DETACH时调用OPENSSL_thread_stop()释放PTD(即per-thread-data)                      。

2       、静态链接到log4cplus时,需要在DLL_THREAD_DETACH时调用log4cplus::threadCleanup()释放per-thread-data       。

3                      、libzip有两个坑(其文档写得不甚清楚):

一              、zip_close()会顺带将关联的zip source的句柄也关闭                      ,所以对应的zip source句柄不要再单独关闭              。

如果要保留zip source句柄另作他用                      ,需要在zip_close()之前先用zip_source_keep()将zip source的句柄引用计数加1                      。

二       、zip source句柄用zip_source_free()释放,而不是用zip_source_close()       。

zip_source_free()还有限制              ,参看其文档       。

参考:

https://github.com/KindDragon/vld/issues/86
声明:本站所有文章                      ,如无特殊说明或标注       ,均为本站原创发布                      。任何个人或组织              ,在未征得本站同意时                      ,禁止复制                      、盗用              、采集、发布本站内容到任何网站                      、书籍等各类媒体平台              。如若本站内容侵犯了原著者的合法权益       ,可联系我们进行处理       。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
网址百度收录怎么查(提升网站曝光率,百度收录站长工具助你一臂之力) echarts y轴设置(echarts的xAxis和yAxis——x轴y轴以及网格线的详细配置)