一連の状況下で非常に具体的なクリーンアップ クラッシュが発生し、何が起こっているのか完全にわからなくなったので、条件/プログラムとその動作について説明します。
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();
それはうまくいきます。動作しないのは、ウィンドウの赤い「X」をクリックして、処理していない WM_QUIT を呼び出す場合です (理由がないはずです)。これが発生しても、メッセージ ループは終了し、アプリは必要に応じて 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/unit 呼び出しにラップしました。
// 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を介してクリーンアップした場合にのみ問題が発生するのは私だけですか?):デストラクタ で継承されたIUnknown::Release()を呼び出す