卸载MFC DLL时出现内存泄露
2013-05-16 22:22
288 查看
一、现象描述
在
时出现一堆的内存泄露。
二、造成原因
1、加载DLL与卸载DLL不在同一线程.
2、
三、解决方法
1、
让加载DLL与卸载DLL在同一线程.
2、
修改:在载入DLL后,调用GetModuleHandleEx使所有的DLL都是静态卸载,相当于用了导出库.这样DLL会在ExitProcess的时候才卸载
参考文章:http://www.cnblogs.com/crazii/articles/1762296.html
很久就发现了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
}
在
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
}
相关文章推荐
- MFC和opencv一起使用时会莫名奇妙出现内存泄露问题
- 关于在VS2008以下版本的MFC程序使用VS 2008 FeaturePack出现内存泄露的理解
- 关于在VS2008以下版本的MFC程序使用VS 2008 FeaturePack出现内存泄露的理解
- 关于DLL工程中存在全局变量可能导致MFC内存泄露误报的原因分析及解决办法
- 关于DLL工程中存在全局变量可能导致MFC内存泄露误报的原因分析及解决办法
- 关于DLL工程中存在全局变量可能导致MFC内存泄露误报的原因分析及解决办法
- WINCE-MFC-CDC使用出现的4KB内存泄露解决办法,坑爹的MFC
- WINCE-MFC-CDC使用出现的4KB内存泄露解决办法,坑爹的MFC
- Win8系统出现内存泄露导致黑屏、死机、卡顿的解决方法
- android中常出现的内存泄露问题
- 已安全化的ActiveX控件卸载时出现"DllUnregisterServer函数出错,错误代码:0x80070002"问题解决
- 内存泄露检测之MFC
- java内存泄露,在什么地方最有可能出现内存泄露?
- 使用SOS.dll调查内存泄露
- MFC内存泄露检测
- 浅谈MFC内存泄露检测及内存越界访问保护机制
- mfc框架下osg的内存泄露问题(转)
- 关于 MFC 中 CString 内存泄露的问题
- Iphone开发(6) 如何保证不出现内存泄露
- MFC下读写Excel文件,出现_malloc_dbg的内存错误