现在的位置: 首页 > 综合 > 正文

内存泄漏

2013年05月29日 ⁄ 综合 ⁄ 共 1742字 ⁄ 字号 评论关闭

1. 关于MFC 加载多个dll 时CDynLinkLibrary 内存泄漏误报

转自: http://hi.baidu.com/boboduck/blog/item/1547f12a65d38f92023bf63f.html

 

最近 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 里给出了一个其实没什么用的补救措施:在模块卸载时输出分隔调试信息以便于将误报与真正的内存泄漏区分出来。

--------------------------------------------------------------------------------------------------------------------

detect memory leak!

f:/rtm/vctools/vc7libs/ship/atlmfc/src/mfc/strcore.cpp(141)   ......

查看output窗口,程序中不知何时出现了内存泄露的问题。经过一阵排查,发现是由于一个函数在两个模块中的字符串参数类型定义不一致引起的。该函数实现在EXE中,参数定义为BSTR,在DLL中进行调用(回调喽),DLL中将函数原型参数定义为CString。这样一来编译器是无法发现问题的。
想必是DLL原本传了一个CString过去,中途mfc发现需要转换成BSTR,于是只好苦水往肚里咽,偷偷分配了一块内存,变成了BSTR,临了也没人知道那块内存要释放。

抱歉!评论已关闭.