noslopforever [天堂里的死神]

我浴血奋战,只为了神圣永久不变的传言

用户操作
[即时聊天] [发私信] [加为好友]
noslopforever(天堂里的死神)ID:noslopforever
73171次访问,排名1394好友4人,关注者11
3D、图形学、游戏、哲学、历史、音乐,一个都不能少。
noslopforever的文章
原创 85 篇
翻译 2 篇
转载 4 篇
评论 208 篇
noslopforever(天堂里的死神)的公告

-欢迎大家来到我的空间。这里关注游戏相关学科的问题。
-自我介绍:男,25岁,程序员,喜欢战争、历史和哲学题材游戏。作为一位普通的初学者,希望众位前辈们能多多包涵和帮助。
-欢迎大家拍砖。本Blog原创的文章,如要转载,请注明出处和姓名。本Blog放置的代码,大部分是伪码,不保证能够运行。
*留言本1:没有CSDN帐号的网友留言请点击此链接
*留言本2:CSDN网友请在个人空间留言 ^_^




烽火过千年,往事如烟。争斗一生归何处?黄土青山。 繁华总易逝,回首不堪。敢叫天地换新颜,铁马连天。 ——《无题》 李巍于2008年6月9日

-最近在做:做好自己的项目,安排自己的时间。

-有些栏目的文章是不放在主页显示的,如果有感兴趣的可以到相应栏目查询。杂项和Just As Gamer栏目的,仅作为个人喜好,恕不回复。

最近评论
网民:理想是一种境界,有时需要用一生来努力而见不到结果.
能在寻觅的路上品尝着奋斗的过程,这是最重要的!
johnson3d:很高兴看到你越来越成熟了,无论是技术,还是性格。
性格上,我觉得你应该更加自信一点,你很强!
技术上,我希望你还能够在一点上提高,那就是更快的找到开发(不是性能- -!)主要瓶颈,并且解决他。
这几天有空我们去物美把卡花了哈:)
同行:读完这篇文章内心很有触动!
在还年轻的岁数能悟出如此深而大气的道理,在以后的人生道路上应该没什么事能难倒你!
人生一生不可能什么都做的完美,为目标求大同,有取舍是大智慧!
同行:读完这篇文章内心很有触动!
在还年轻的岁数能悟出如此深而大气的道理,在以后的人生道路上应该没什么事能难倒你!
人生一生不可能什么都做的完美,为目标求大同,有取舍是大智慧!
同行:每个人刚工作时都有这种经历.
人都是在干中学习,都是从弱到强,没有生而知之者.
所谓有经验的人不过是教训或经历比你多些就是了.
即使不成功经验也是收获!
在咱们业内早二三年都是师!不敢太谦虚了!
文章分类
收藏
相册
misc杂项
朝圣者的路途
文档所需图片册
我的书单
我的照片
!飞龙在天!
cproom前辈的Blog
eXtreme 3D —— Dreams的Blog(RSS)
flymemory的Blog
johnson的Blog——我的老师和第一个上司 ^_^
nhsoft——野猪大大的Blog
Nightmare of Design/Dev(RSS)
游戏编程实践——我的老师的Blog
马肝前辈的Blog
!虎狼成群!
亮——同学、引擎程序员
江自流——另一位同学兼才思敏捷的策划
游戏王——同学,一位才思敏捷的策划
推荐网页
Boost——C++准标准库
Boost中文站
GameDev.net
OGRE3D中文站
OGRE3D——开源的3D图形引擎
Sourceforge
有关WOW格式的Wiki
涂鸦软件——一个很牛的国产游戏引擎
喜欢的站点
《闪电战》杂志讨论区
帝国之鹰
德军总部
英雄世界
存档
软件项目交易
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 DXUT库,CDXUTDialogResourceManager的一个不太好发现的问题收藏

新一篇: 搞定室内空间bsp分割,发文祝贺! | 旧一篇: 方便的boost_python

 

如果按照DXUT例子的编码方式,很难出现这个问题的,但是这两日闲来无事,将DXUT分到了一个DLL内,结果……
退出时报错!

不断注释代码,最后发现是CDXUTDialogResourceManager惹的祸。再一检查,有些心得,遂拿来共享。


原因是这样的:
CDXUTDialogResourceManager在析构函数里干掉Cache(Delete):
//--------------------------------------------------------------------------------------
CDXUTDialogResourceManager::~CDXUTDialogResourceManager()
{
    int i;
    for( i=0; i < m_FontCache.GetSize(); i++ )
    {
        DXUTFontNode* pFontNode = m_FontCache.GetAt( i );
        SAFE_DELETE( pFontNode );
    }
    m_FontCache.RemoveAll();   

    for( i=0; i < m_TextureCache.GetSize(); i++ )
    {
        DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i );
        SAFE_DELETE( pTextureNode );
    }
    m_TextureCache.RemoveAll();   

    CUniBuffer::Uninitialize();
    CDXUTIMEEditBox::Uninitialize();
}
//--------------------------------------------------------------------------------------



而在OnDestroyDevice里真正Release这些资源:
//--------------------------------------------------------------------------------------
void CDXUTDialogResourceManager::OnDestroyDevice()
{
    int i=0; 

    m_pd3dDevice = NULL;

    // Release the resources but don't clear the cache, as these will need to be
    // recreated if the device is recreated
    for( i=0; i < m_FontCache.GetSize(); i++ )
    {
        DXUTFontNode* pFontNode = m_FontCache.GetAt( i );
        SAFE_RELEASE( pFontNode->pFont );
    }
    
    for( i=0; i < m_TextureCache.GetSize(); i++ )
    {
        DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i );
        SAFE_RELEASE( pTextureNode->pTexture );
    }

    SAFE_RELEASE( m_pSprite );
}
//--------------------------------------------------------------------------------------
一般说来,在例子中,这个RM都是以全局变量形式存在的:
extern CDXUTDialogResourceManager g_DialogResourceManager; // manager for shared resources of dialogs

这就有一个问题,OnDestroyDevice和析构函数究竟哪个在先?这就要看OnDestroyDevice的最终调用者DXUTState这个全局变量和g_DialogResourceManager这个全局变量的析构先后顺序了。
一般,如果这些代码和您的代码都编译到一个EXE,则顺序大凡是先State析构,调用DestroyDevice再RM析构,这就对了,既Release又Delete。
而在将DXUT封到Dll后,便发生了位于Dll的State后于位于EXE 的 RM析构的情况,这导致了先调用了RM的析构函数,然后才调用了State析构和OnDestroyDevice!!!
这意味着先调用了Delete,然后在Release的时候就找不着北了,资源没有Release,DXUT自然会报错!


由此得出一个结论:VC的CRT在退出时,先干掉了EXE本身的全局变量,然后才去释放各个DLL……
写到这里后,又发现DXUTState是一个非导出类,遂导出之,结果依旧……
不知对否,遂又作测试,发现凡是EXE中的全局变量,全都在Dll的State前析构。
extern CDXUTDialog             g_HUD;                  // dialog for standard controls
extern CDXUTDialog             g_SampleUI;             // dialog for sample specific controls
皆如此。

解决的方案就近乎简单了,DialogRM 既然都析构了,何不调用自己的Release?为何一定要在State析构时才调用呢?
因此为增加一句:
CDXUTDialogResourceManager::~CDXUTDialogResourceManager()
{
[color=blue] /////////////////////////////////////////////////
OnDestroyDevice();
/////////////////////////////////////////////////
[/color]
    int i;
    for( i=0; i < m_FontCache.GetSize(); i++ )
    {
        DXUTFontNode* pFontNode = m_FontCache.GetAt( i );
        SAFE_DELETE( pFontNode );
    }
    m_FontCache.RemoveAll();   

    for( i=0; i < m_TextureCache.GetSize(); i++ )
    {
        DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i );
        SAFE_DELETE( pTextureNode );
    }
    m_TextureCache.RemoveAll();   

    CUniBuffer::Uninitialize();
    CDXUTIMEEditBox::Uninitialize();
}

去掉其他地方对RM 的OnDestroyDevice 的调用。
再编译连接,成功,不会再在退出时报错了。

结论:
该谁的事情谁自己处理,别让别人擦屁股,否则总会受人牵制。

欢迎大家指正 ^_^


发表于 @ 2006年03月07日 00:55:00|评论(loading...)|编辑

新一篇: 搞定室内空间bsp分割,发文祝贺! | 旧一篇: 方便的boost_python

评论

#fannyfish 发表于2006-07-03 17:55:00  IP: 61.51.111.*
我建了个游戏开发的交流圈子, 把你的BLOG加进去了.
圈子地址是: http://blog.csdn.net/group/fannyfish/
发表评论  


登录
Csdn Blog version 3.1a
Copyright © noslopforever(天堂里的死神)