Ogre与MFC结合时的内存泄漏问题
来源:互联网 发布:体彩网络销售平台 编辑:程序博客网 时间:2024/04/28 22:03
转载自:http://hi.baidu.com/monboy/item/5e06ccefaa50a80c65db0091
刚开始使用Ogre时总是碰到内存泄露,而且往往是一泄千里,等半分钟才能打完日志,我想这和Ogre中的大量大对象很有关系。下面就来分析一下内存泄露的产生原因。
1. MFC中使用Ogre时发生的内存泄露
这个问题比较有意思,其实并没有发生泄露,而是MFC自作主张的认为发生了内存泄露,实际上内存并不是没有释放,而是在VC报内存泄露之后释放,先来看一看MFC报内存泄露时的调用堆栈:
msvcr71d.dll!_CrtDumpMemoryLeaks() 行2208 C
mfc71d.dll!_AFX_DEBUG_STATE::~_AFX_DEBUG_STATE() 行127 C++
mfc71d.dll!_AFX_DEBUG_STATE::`scalar deleting destructor'() + 0xf C++
mfc71d.dll!CProcessLocalObject::~CProcessLocalObject() 行472 + 0x26 C++
mfc71d.dll!CProcessLocal<_AFX_DEBUG_STATE>::~CProcessLocal<_AFX_DEBUG_STATE>() + 0xf C++
mfc71d.dll!$E10() + 0xd C++
mfc71d.dll!_CRT_INIT(void * hDllHandle=0x7c140000, unsigned long dwReason=0, void * lpreserved=0x00000001) 行234 C
mfc71d.dll!_DllMainCRTStartup(void * hDllHandle=0x7c140000, unsigned long dwReason=0, void * lpreserved=0x00000001) 行288 + 0x11 C
AFX_DEBUG_STATE的析构函数:
_AFX_DEBUG_STATE::~_AFX_DEBUG_STATE()
{
#ifndef _AFX_NO_DEBUG_CRT
_CrtDumpMemoryLeaks();
int nOldState = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
_CrtSetDbgFlag(nOldState & ~_CRTDBG_LEAK_CHECK_DF);
_CrtSetReportHook(pfnOldCrtReportHook);
_CrtSetDumpClient(pfnOldCrtDumpClient);
#endif // _AFX_NO_DEBUG_CRT
}
很显然CrtDumpMemoryLeaks()是在mfc71d.dll卸载时被调用的,如果这个时候OgreMain_d.dll还没有卸载,那么在Ogre中new的全局变量也就还没有释放,所以MFC会认为产生了内存泄露。如何处理这样的问题呢。很简单,让OgreMain_d.dll在mfc71d.dll之前析构,但是默认的MFC程序似乎不是这样干的(为什么呢?),这就要求对项目设置作一点调整,使得Mfc71d.dll在OgreMian之前被链接,这样程序运行时MFC71d就会早于Ogre加载,也就晚于Ogre卸载。具体设置如下:
i) in the General tab, switch "Use MFC in a shared DLL" to "Use Standard Windows Libraries"
ii) in the C/C++/Preprocessor tab, add _AFXDLL to the preprocessor definitions
iii) in the Linker/Input tab, add mfc80d.lib anywhere before OgreMain_d.lib
另一种方法是,使用Ogre自己的MemoryManager,并且禁止调用MFC的DEBUG_NEW,这需要先
#define OGRE_DEBUG_MEMORY_MANAGER 1
然后删除cpp中的以下行
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
这样Ogre中会使用自己的new/delete,而不是调用vccrt中的_heap_alloc_debug
2. Ogre中的对象没有释放
由于Ogre中的很多对象并不是只要delete Root就可以释放的。最好所有的对象都不要自己new,而是通过Ogre::Root,Ogre::SceneManager等创建,这些对象在Root析构时会自己销毁,但是对于从Ogre类派生的类,由于Ogre不存在Create这些类的函数,所以只能在自己的代码中new产生,并由自己负责析构了,比如MovableObject派生的MovableText。当然Ogre也会给你一个将新对象加入其管理的接口,对于MovableText就必须再实现一个MovableTextFactory才行。总之要小心小心再小心。
最后抱怨一下Ogre太大了,有一个OgreLite就好了。现在这样使用起来光链接都要半天,真是太夸张了,所以没事最好不要修改Ogre库,呵呵。
第一步,是卸载dll先后顺序的问题,让OgreMain_d.dll在mfc80d.dll之前析构,老外早就有分析了:
i) in the General tab, switch "Use MFC in a shared DLL" to "Use Standard Windows Libraries"
ii) in the C/C++/Preprocessor tab, add _AFXDLL to the preprocessor definitions
iii) in the Linker/Input tab, add mfc90ud.lib anywhere before OgreMain_d.lib
第二步,删除自己代码中的所有的#defin new DEBUG_NEW,然后在 CApp的构造函数中加入 AfxEnableMemoryTracking(FALSE);
机子本来不快,这样总不至于程序结束的时候慢死。。。自己写代码注意内存问题
出现错误:
1>Compiling...
1>stdafx.cpp
1>d:/program files/microsoft visual studio 9.0/vc/atlmfc/include/afxver_.h(81) : fatal error C1189: #error : Please use the /MD switch for _AFXDLL builds
解决方法:
c/c++ ---- Code Generation --------- runtime library 改为 “Multi-threaded Debug DLL (/MDd)”
- Ogre与MFC结合时的内存泄漏问题
- Ogre与MFC结合时的内存泄漏问题
- Ogre与MFC结合时的内存泄漏问题
- OGRE与MFC结合产生的内存泄露问题
- ogre与mfc结合
- MFC 内存泄漏问题
- ACE与MFC一起使用时内存泄漏的解决方法
- OpenCV+MFC 内存泄漏问题
- MFC内存泄漏的问题的其中一种情况
- MFC双缓冲技术的内存泄漏问题探究
- 关于使用MFC DLL时提示内存泄漏问题
- MFC多线程内存泄漏问题&解决方法
- Android内存泄漏简介 与 android内存泄露的问题
- ogre与CEGUI结合
- 处理内存泄漏的一种MFC方法
- VC/MFC 内存泄漏的个人总结
- 关于MFC的内存泄漏误报
- MFC 控件引起的内存泄漏
- 孙子兵法(曹操注)
- Lint删除未引用的资源
- 开发人员一定要加入收藏夹的网站
- 基础总结篇之五:BroadcastReceiver应用详解
- Linux 下使用 adb 和 fastboot 命令
- Ogre与MFC结合时的内存泄漏问题
- awk应用小结(所有命令行均经调试)
- 【C++基础】sprintf使用的方法与printf的区别
- 我的Java开发学习之旅------>Java 格式化类(java.util.Formatter)基本用法
- java学习之路--java数组--java开发实战经典第四章
- awk 手册
- java线程同步经典——生产者消费者
- WindowsXP的图标结构
- OSG中的相关词汇表