DXUT库,CDXUTDialogResourceManager的一个不太好发现的问题
2006-03-07 00:55
302 查看
如果按照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 的调用。
再编译连接,成功,不会再在退出时报错了。
结论:
该谁的事情谁自己处理,别让别人擦屁股,否则总会受人牵制。
欢迎大家指正 ^_^
退出时报错!
不断注释代码,最后发现是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 的调用。
再编译连接,成功,不会再在退出时报错了。
结论:
该谁的事情谁自己处理,别让别人擦屁股,否则总会受人牵制。
欢迎大家指正 ^_^
相关文章推荐
- leakcanary作者发现的一个Dialog的各种listener容易引发的内存泄露问题
- 发现一个奇怪的问题: 不能把文件取名为 con
- 发现JavaScript中Number的toFixed()四舍五入时的一个问题,请教大虾!(原来是浏览器问题)
- 发现一个bug JasperRunManager.runReportToHtmlFile
- 刚刚发现的一个小问题的解决办法(datalist绑定和itemcommand)
- 发现IE中文本框的一个问题
- [置顶] 猴子吃桃子问题:猴子第一天摘了若干个桃子,当时吃了若干个,还不瘾,又多吃了一个,第二天早上,又将剩下的桃子吃掉了一半,又多吃了一个。以后每一天早上都吃前一天剩下的一半零一个,直到第十天发现剩一个了,求
- ARCGISENGINE给要素赋值时发现的一个问题
- 发现一个vs母版页问题
- 在使用JdbcTemplate.queryForMap(String )的时候发现一个问题.
- 【问题记录】uwsgi部署并启动俩个几乎一样的python flask web app,发现有一个app响应时间非常长
- 分享一个服务器重启问题发现的过程
- 发现一个问题 搞了半天啊 jQuery 属性过滤问题
- 发现一个问题,有个类没法实例化~(IDE问题,已经OK)
- 安装Oracle9i时发现了一个新问题!
- 发现一个很牛B的问题
- 今天发现了一个sql的小问题
- 有关从经典部署模型迁移到 Azure Resource Manager 部署模型的常见问题
- 发现一个问题。。
- 传递对象时发现的一个有趣的小问题