You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

释放IWICImagingFactory COM对象时程序关闭触发段错误求助

问题分析与解决方案

你的段错误根源是未正确初始化COM库,同时消息循环和资源释放的逻辑也存在问题,具体如下:

核心问题

  • COM库未初始化:WIC(Windows Imaging Component)是基于COM的组件,调用CoCreateInstance创建IWICImagingFactory前,必须先调用CoInitialize或CoInitializeEx初始化COM环境。未初始化的情况下,COM对象的创建和释放都会触发内存错误。
  • 消息循环逻辑错误:当前代码中仅在msg.message == WM_QUIT时才释放资源,但PeekMessage在无消息时msg的内容是未定义的,可能导致资源释放逻辑被跳过或错误触发。
  • 资源释放顺序与时机错误:CoUninitialize必须在所有COM对象释放完成后调用,否则会导致已释放的COM对象引用无效内存。

修正后的代码

#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)
{
    // 初始化COM库(单线程公寓模型,适合Direct2D/WIC场景)
    HRESULT hr = CoInitialize(nullptr);
    if (FAILED(hr))
    {
        return -1;
    }

    // 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 = nullptr;
    ID2D1HwndRenderTarget *pRT = nullptr;
    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 = nullptr;
    CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pWICFactory));

    // Start loop
    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);

        // 渲染逻辑放在消息处理后,避免消息堆积
        if (pRT != nullptr)
        {
            pRT->BeginDraw();
            pRT->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
            HRESULT drawHr = pRT->EndDraw();
            // 处理渲染目标丢失的情况(比如窗口大小变化)
            if (drawHr == D2DERR_RECREATE_TARGET)
            {
                // 这里可以重新创建渲染目标,示例中简化处理
                SafeRelease(pRT);
                GetClientRect(hWnd, &rc);
                pD2DFactory->CreateHwndRenderTarget(
                    D2D1::RenderTargetProperties(),
                    D2D1::HwndRenderTargetProperties(hWnd, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)),
                    &pRT);
            }
        }
    }

    // 按依赖顺序释放资源:先释放依赖对象,再释放工厂
    SafeRelease(pRT);
    SafeRelease(pD2DFactory);
    SafeRelease(pWICFactory);

    UnregisterClass(L"Class Name", hInst);
    // 所有COM对象释放完成后,关闭COM库
    CoUninitialize();

    return static_cast<int>(msg.wParam);
}

关键修改点说明

  • 添加COM初始化:在程序开头调用CoInitialize(nullptr),使用单线程公寓(STA)模型,这是Direct2D和WIC推荐的线程模型。
  • 修正消息循环:改用GetMessage替代PeekMessage的循环方式,更符合Windows消息循环的标准写法,确保收到WM_QUIT后才退出循环。
  • 调整资源释放顺序:先释放ID2D1HwndRenderTarget(依赖ID2D1Factory),再释放ID2D1Factory和IWICImagingFactory,最后调用CoUninitialize。
  • 添加渲染错误处理:处理EndDraw返回的D2DERR_RECREATE_TARGET错误,避免窗口大小变化导致的渲染异常。

编译命令保持不变

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

内容的提问来源于stack exchange,提问作者SetupWizard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:42:08