MFC 加载多个dll 时CDynLinkLibrary 内存泄漏误报

2008-11-13 16:11:42 旧日重来

最近 Perry 在写一个简单的插件系统框架,需要有 n 多动态链接库加载来加载去的。调试时偶然发现提示在 dllmodul.cpp 中会报告若干个跟 CDynLinkLibrary 相关的内存泄漏。错误信息具体看起来大概是这个样子:

Detected memory leaks!
Dumping objects ->
...\atlmfc\src\mfc\dllmodul.cpp(133) :
  {410} client block at 0x05A919F8, subtype c0, 64 bytes long.
a CDynLinkLibrary object at $05A919F8, 64 bytes long
a CDynLinkLibrary object at $05A919F8, 64 bytes long
{405} client block at 0x05A93F28, subtype c0, 64 bytes long.
a CDynLinkLibrary object at $05A93F28, 64 bytes long
a CDynLinkLibrary object at $05A93F28, 64 bytes long
{65} client block at 0x002C2C90, subtype c0, 64 bytes long.
a CDynLinkLibrary object at $002C2C90, 64 bytes long
a CDynLinkLibrary object at $002C2C90, 64 bytes long
Object dump complete.

着实让人摸不着头脑。无奈求助 Google,结果搜到了 MS 的 KB 167929 专门说这个的,另有一个机器翻译的中文版,不过译的实在惨不忍睹,还是看英文的靠谱些……

首先最重要的一点是,这个内存泄漏是误报,所以大可以不去管它。究其原因,是 MFC 程序加载 MFC DLL(或非 MFC 程序加载了多个 MFC DLL)时,并且这些模块都是共享 MFC 的运行时库(即链接时启用了“Use MFC in a Shared DLL”),但是它们又需要加载不同版本的 MFC 运行时库的情况下,不同版本的 MFC 运行时库分别管理各自的状态,因此造成内存中存在多个 MFC 的状态拷贝,本来这种情况其实是正常的,但调试器会误以为发生了错误。

一个典型的造成这种误报发生的情况就是有些模块要求加载 ANSI (MBCS) 版本的 MFC DLL,而另一些要求 Unicode 版本的 MFC DLL。在 Visual Studio 2005 中,默认的 C++ 工程是 Unicode 的,但有时为了考虑对 Win9x 系统的兼容性,往往会改成 MBCS 编译,和其他模块组合时就可能会造成版本不一致。

尽管 MS 已经明确了这是个误报,却仍然宣称这是 by design 的,不会改正。如果不是自己写的 DLL 无法修改的话,基本是没有办法避免这个烦人的误报了。另外,KB 167929 里给出了一个其实没什么用的补救措施:在模块卸载时输出分隔调试信息以便于将误报与真正的内存泄漏区分出来。

查看:原文地址;来源:live.aulddays.com


注意:本站所有文章除特别说明外均为原创,版权所有,转载请务必以超链接方式注明作者出处,并禁止用作商业用途