由激活上下文引起的动态加载DLL上的文件句柄泄漏

时间:2010-07-04 04:41:45

标签: c++ windows dll memory-leaks handle

我有动态加载&卸载的DLL,需要COMCTL32.dll> = v6.0和MSVCR> = v9.0。为确保加载了正确的版本,我在Visual Studio项目设置中启用了清单文件生成,并将此条目添加到另一个清单文件中:

<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>

在测试程序中,我调用LoadLibrary()后跟{DLL}的FreeLibrary(),ProcessExplorer指示以下文件句柄泄露:

  • C:\ Windows \ WinSxS文件\ x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e
  • C:\ Windows \ WinSxS文件\ x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.5512_x-ww_35d4ce83

从反汇编调用堆栈跟踪中我了解到,在LoadLibrary()上,自动创建了激活上下文,并打开了每个文件夹的句柄。但似乎未在FreeLibrary()上删除激活上下文。

如果我删除清单文件并设置项目设置以禁用清单生成,则这些泄漏消失了。但是,这样我就无法确保使用正确的MSVCR和COMCTL,因为这个DLL是由我无法控制的进程加载的。

有没有办法在不删除清单文件的情况下删除此泄漏

谢谢!

4 个答案:

答案 0 :(得分:1)

ProcessExplorer HANDLE泄漏报告是激活上下文泄漏的症状。很可能这个泄漏是间接在你的代码中,因为你没有正确地调用MFC。

为了帮助您自己验证这是您的错误而不是MFC,您可以从AppWizard创建一个简单的MFC DLL而不需要任何代码,并确认当它是LoadLibrary / FreeLibrary多次时,没有累积泄漏。

缺少的OS调用是ReleaseActCtx,或者是导致释放失败的缺少DeactivateActCtx。在实践中,MFC正在为您调用这些函数,因此您将寻找某种类型的MFC调用。

最好的调试技术可能是跟踪或断开核心激活上下文创建/激活/停用/释放功能(http://msdn.microsoft.com/en-us/library/aa374166(VS.85)。 aspx)看看会发生什么。您可能会看到一堆调用,因此可能需要进行某种跟踪。理想情况下,您可以在每次调用时捕获callstack并查看它们。您的调试器可能可以帮助您执行此操作。最新版本的VS可以在遇到断点时运行宏。

顺便说一句,你是正确的,你需要清单文件,不应该删除它们。

马丁

答案 1 :(得分:1)

ProcessExplorer HANDLE泄漏报告是激活上下文泄漏的症状。很可能这种泄漏是间接在你的代码中,因为你没有正确地调用MFC。

与特定代码使用无关。该问题已得到Microsoft的确认:http://support.microsoft.com/kb/2624911

在调用UnregisterClass时,SHELL32.DLL中确实存在上下文激活泄漏,从而影响Windows Vista及更高版本。该问题的唯一解决方法是不重复加载和卸载SHELL32.DLL。微软正在考虑在较新版本的Windows中修复此问题。

答案 2 :(得分:0)

这些句柄可能不会泄露 - 只是缓存。如果您将测试程序更改为多次重复加载和卸载DLL,那么每次DLL卸载时是否会看到一对新的句柄泄漏?如果没有,那不是问题。

答案 3 :(得分:0)

您的DLL是否有机会使用MFC? 我有一个DLL的问题,它使用MFC并调用可能相关的AfxWinInit()。这个DLL(错误地)反复调用AfxWinInit(),结果发现它泄漏了每个调用的激活上下文。令人惊讶的是,这只发生在调用应用程序使用清单时。