卸载MFC DLL时出现内存泄露



一、现象描述

if ( m_hDll )
	{
		::FreeLibrary((HMODULE) m_hDll);
		m_hDll = NULL;
	}

时出现一堆的内存泄露。


二、造成原因

1、加载DLL与卸载DLL不在同一线程.

2、


三、解决方法

1、

让加载DLL与卸载DLL在同一线程.


2、

修改:在载入DLL后,调用GetModuleHandleEx使所有的DLL都是静态卸载,相当于用了导出库.这样DLL会在ExitProcess的时候才卸载

m_hDll = (HMODULE)::LoadLibrary(lpDllPath ? lpDllPath : "YourMFCPlugin.dll");
	GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_PIN,(LPCTSTR)m_hDll,&m_hDll);

参考文章:http://www.cnblogs.com/crazii/articles/1762296.html

去掉MFC的内存泄露报告 - bypass MFC's memory leak dump

很久就发现了MFC的内存泄露报告,原因是我把MFC的界面做成了动态加载的插件(Framework本身不是基于MFC的),它作为DLL在其他一些插件之后被加载.卸载的时候在其他DLL之前先被卸载,所以在MFC出内存泄露报告的时候,全局静态对象并没有完全析构.

其实这里MFC给出的内存泄露报告都是不精确的.

于是在加载MFC DLL的时候加上了GetModuleHanldeEx(GET_MODULE_HANDLE_EX_FLAG_PIN)参数,使所有的DLL都是静态卸载,相当于用了导出库.这样DLL会在ExitProcess的时候才卸载,MFC的Dump也在这个时候才开始,问题好了很多.

//MainApp/Framework is NOT based on MFC lib.
//hPlugin = LoadLibrary("YourMFCPlugin.dll"); //load a DLL that uses MFC lib

//GetModuleHanldeEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_PIN,(LPCTSTR)hPlugin,&hPlugin);

 

深入讨论:

还有更恼人的问题,由于自己实现了内存管理,内存管理对象MemoryManger作为系统的最后一个对象被析构,而即使让MFC的DLL静态释放,它还是在基础DLL的静态对象MemoryManger析构之前就dump memory leak了,所以情况就是,

MFC生成了一份不精确的memory leak report,紧接着MemoryManger对象也生成了另一份report.如果自己实现了一个Memory Manager,那么这个MFC的内存报告确实有点不爽,不能配置其关闭.


我查了半天没有找到如何关闭MFC的report,

最后用了一个很无奈的办法:将crt的debug输出定位到stderr,等到要生成自己的memory report的时候,再从新设置回来,由于程序是windows程序,所以实际上MFC的没有输出.至少在Output窗口没有MFC的内存泄露报告了.
我的基本思路记录如下,也希望对遇到类似问题的人有所帮助:

 

//sample code by Crazii

/* @brief : memory manager initialize - bypass the MFC's memory leak dump output */

MemoryManger::MemroyManger()

{

#if WIN32

//将CRT Debug Reprt定位到stderr
//redirect internal CRT Debug output to stderr,instead of using system OutputDebugString
//you can redirect it to any other real hdd log file,too.
  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
  _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);

#endif //WIN32

}

 

/* @brief : memory manager shutdown, dump the real memory leak */

MemoryManger::~MemroyManger()

{

#if WIN32

//恢复DebugOutput

//restore the CRT output

  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);

 

//TODO:

//Dump your "Real" Memory Leaks

//OutputDebugString...

 

//finally: dump default leaks that may be out of memory manager's control
_CrtDumpMemoryLeaks();

 

#endif //WIN32

}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值