Ogre中的内存泄露

刚开始使用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库,呵呵。

posted on 2007-06-17 16:44 雁过无痕 阅读(4729) 评论(5)  编辑  收藏

评论

# re: Ogre中的内存泄露 2008-11-18 10:30 AlexQ

很管用 谢谢  回复  更多评论   

# re: Ogre中的内存泄露 2009-01-02 01:33 geeeeeeee

按第一种方法有如下错误
1>msvcrtd.lib(crtexew.obj) : error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用  回复  更多评论   

# re: Ogre中的内存泄露 2009-01-02 01:34 geeeeeeee

可能是UNICODE问题不知如何解决  回复  更多评论   

# re: Ogre中的内存泄露 2009-07-26 16:22 yyyy

谢谢,我也正好遇到此问题,按你的方法解决了  回复  更多评论   

# re: Ogre中的内存泄露 2012-08-31 15:08 Carefree

你好,不知道现在楼主还研究OGRE么?
我用ogre1.8也遇到了内存泄露的问题,但按楼主的办法没有效果。  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
<2012年8月>
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

导航

统计

常用链接

留言簿(7)

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜