c++comdirectxdirect2d

I get a Seg Fault when releasing COM object (WICImagingFactory)


I've begun creating a simple game engine using Direct2D, but I've encountered an issue of getting a seg fault whenever I release the IWICImagingFactory*. The issue only occurs when the program is closed.

Minimal Reproducible Sample:

#include <Windows.h>
#include <d2d1.h>
#include <wincodec.h>

template <class Interface>
void SafeRelease(
    Interface *&pInterfaceToRelease)
{
    if (pInterfaceToRelease != nullptr)
    {
        pInterfaceToRelease->Release();
        pInterfaceToRelease = nullptr;
    }
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR pCmdLine, int nCmdShow)
{
    // Register Window Class
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInst;
    wc.lpszClassName = L"Class Name";
    RegisterClass(&wc);

    // Create and Show Window
    HWND hWnd = CreateWindowEx(0, L"Class Name", L"Test Window", WS_OVERLAPPEDWINDOW,
                               CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                               NULL, NULL, hInst, NULL);
    ShowWindow(hWnd, nCmdShow);

    // Create d2d factory and render target
    ID2D1Factory *pD2DFactory;
    ID2D1HwndRenderTarget *pRT;
    D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory);
    RECT rc;
    GetClientRect(hWnd, &rc);
    pD2DFactory->CreateHwndRenderTarget(
        D2D1::RenderTargetProperties(),
        D2D1::HwndRenderTargetProperties(hWnd, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)),
        &pRT);

    // Create Imaging Factory
    IWICImagingFactory *pWICFactory;
    CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pWICFactory));

    // Start loop
    bool windowOpen = true;
    MSG msg;
    while (windowOpen)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if (msg.message == WM_QUIT)
        {
            SafeRelease(pWICFactory);
            SafeRelease(pRT);
            SafeRelease(pD2DFactory);
            UnregisterClass(L"Class Name", hInst);
            CoUninitialize();
            windowOpen = false;
            break;
        }

        pRT->BeginDraw();
        pRT->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
        pRT->EndDraw();
    }

    return 0;
}

I'm compiling the program using gcc:

g++ -fdiagnostics-color=always -g test.cpp -municode -mwindows -ld2d1 -lole32 -lwindowscodecs -o test.exe

I've tried eliminated any use of the IWICImagingFactory* beyond creating it by not loading any images, but the issue persists. Images still load fine. I also ensured that the pointer isn't null before calling Release().


Solution

  • Thank you to everyone who replied. The issue with the code sample I provided was that it didn't call CoInitialize(), which I forgot to include. The issue with my program itself was that there was an object that held a ID2D1Bitmap* that was created with the IWICImagingFactory and stored in static memory. The problem was that the bitmap was being released after the IWICImagingFactory, which caused a seg fault.