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

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

时间2025-08-05 09:04:11分类IT科技浏览5738
导读:让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
vue的mvc(vue 简介 (MVVM介绍,超详细))