在一系列情况下,我遇到了一个非常具体的清理崩溃,我完全不知道发生了什么,所以我只描述条件/程序以及它在做什么。
我有一个使用 Direct2D 的 win32 程序在黑屏上绘制测试字符串和测试位图。这一切都有效。没有崩溃,根本没有内存泄漏。但是,只有当我通过以下方式退出程序时:
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
PostQuitMessage(0); // close program
break;
这反过来导致我的消息循环结束,调用我的清理代码:
Application app(hWnd);
// message loop
while(true)
{
// Check to see if any messages are waiting in the queue
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// Translate the message and dispatch it to WindowProc()
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// If the message is WM_QUIT, exit the while loop
if(msg.message == WM_QUIT)
break;
// runtime code
app.Update();
// continue...
Sleep(FRAME_DELAY);
}
// cleanup code
app.Delete();
这样可行。如果我在调用 WM_QUIT 的窗口上单击红色的“X”,我没有处理(并且不应该有理由),这不起作用。当这种情况发生时,我的消息循环仍然结束,我的应用程序调用 Delete() ,但它在释放 D2D 对象时特别崩溃。顺序无关紧要,它似乎不依赖于任何其他现有或正在发布/未发布的内容。即使我不加载图像,我的 IWICImagingFactory* 也无法在不崩溃的情况下释放...
D2D::~D2D()
{
// release all bitmaps
for (list<tSprite>::iterator iter = m_vSprites.begin();iter != m_vSprites.end();++iter)
{
SafeRelease(&(iter->m_pImage));
}
SafeRelease(&m_pWICFactory);// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<THIS LINE
SafeRelease(&m_pText);
SafeRelease(&m_pDWFactory);
SafeRelease(&m_pBrush);
SafeRelease(&m_pD2D);
SafeRelease(&m_pD2DFactory);
}
最后我添加了一些代码,偶然地修复了崩溃,但我想知道为什么以及这样做是否正确。我将我的应用程序的生命包装到一个 COM 初始化/单元调用中:
// init code
CoInitializeEx(0,COINIT_DISABLE_OLE1DDE);//<<<<<<<<<<<<<<
Application app(hWnd);
// message loop
while(true)
...
// cleanup code
app.Delete();
CoUninitialize();//<<<<<<<<<<<<<
综上所述,即使没有 COM 代码,程序也可以正常运行并正常退出,除非我单击红色的“X”,在这种情况下,只有 D2D WIC 映像工厂无法发布。
类似的问题(只有我的只有通过 WM_CLOSE 清理时才有问题?): 在析构函数中调用 Inherited IUnknown::Release()