Windows10上でDirect3D11使用時に発生するリークについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
島砂糖

Windows10上でDirect3D11使用時に発生するリークについて

#1

投稿記事 by 島砂糖 » 8年前

Windows10上でDirect3D11の学習をしているのですが、終了処理の際にメモリリークが解消できず、書込をさせて頂きました。
環境はWindows10Pro(64bit)、VisualStudio2015Communityです。

挙動に関して数点下記のような奇妙な点があり、どこに問題があるのか特定できず対処に困っております。
・Windows7(32bit)では発生しません。
・Windows10上であればVisualStudio2010、2013でも発生します。
・Windows10SDK組み込みと2010JuneのいずれのDirectXSDKを使用する設定としても発生します。
・書籍サンプルやWeb上のチュートリアルでも発生します。
・描画時SwapChainのPresentメソッドを実行しないようにすると発生しなくなります。

下記取り急ぎ、サンプルコードを書いてみました。

コード:

#include <windows.h>
#include <d3d11.h>

#pragma comment( lib, "d3d11.lib" )

#define WINDOW_WIDTH  200
#define WINDOW_HEIGHT 200

ID3D11Device* g_pDevice;
ID3D11DeviceContext* g_pDeviceContext;
IDXGISwapChain* g_pSwapChain;
ID3D11RenderTargetView* g_pRenderTargetView;
ID3D11DepthStencilView* g_pDepthStencilView;
ID3D11Texture2D* g_pDepthStencil;

#if defined(DEBUG) || defined(_DEBUG)
// デバッグコンパイルの場合、デバッグレイヤーを有効にする。
// ソフトウェア レイヤー
UINT createDeviceFlag = D3D11_CREATE_DEVICE_DEBUG;
#else
UINT createDeviceFlag = 0;
#endif
#define SAFE_RELEASE(x) if(x){x->Release(); x=NULL;}

void initD3D11(HWND hwnd){
    // デバイス・スワップチェイン作成
    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory(&sd, sizeof(sd));
    sd.BufferCount = 1;
    sd.BufferDesc.Width = WINDOW_WIDTH;
    sd.BufferDesc.Height = WINDOW_HEIGHT;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = hwnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;

    D3D_FEATURE_LEVEL pFeatureLevels = D3D_FEATURE_LEVEL_11_0;
    D3D_FEATURE_LEVEL* pFeatureLevel = NULL;

    D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL,
        createDeviceFlag, &pFeatureLevels, 1, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pDevice,
        pFeatureLevel, &g_pDeviceContext);

    //レンダーターゲットビューの作成
    ID3D11Texture2D *pBackBuffer;
    g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
    g_pDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView);
    SAFE_RELEASE(pBackBuffer);
    //深度ステンシルビューの作成
    D3D11_TEXTURE2D_DESC descDepth;
    descDepth.Width = WINDOW_WIDTH;
    descDepth.Height = WINDOW_HEIGHT;
    descDepth.MipLevels = 1;
    descDepth.ArraySize = 1;
    descDepth.Format = DXGI_FORMAT_D32_FLOAT;
    descDepth.SampleDesc.Count = 1;
    descDepth.SampleDesc.Quality = 0;
    descDepth.Usage = D3D11_USAGE_DEFAULT;
    descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    descDepth.CPUAccessFlags = 0;
    descDepth.MiscFlags = 0;
    g_pDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencil);
    g_pDevice->CreateDepthStencilView(g_pDepthStencil, NULL, &g_pDepthStencilView);
    //レンダーターゲットビューと深度ステンシルビューをパイプラインにバインド
    g_pDeviceContext->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView);
    //ビューポートの設定
    D3D11_VIEWPORT vp;
    vp.Width = WINDOW_WIDTH;
    vp.Height = WINDOW_HEIGHT;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    g_pDeviceContext->RSSetViewports(1, &vp);
    //ラスタライズ設定
    D3D11_RASTERIZER_DESC rdc;
    ZeroMemory(&rdc, sizeof(rdc));
    rdc.CullMode = D3D11_CULL_NONE;
    rdc.FillMode = D3D11_FILL_SOLID;
    ID3D11RasterizerState* pIr = NULL;
    g_pDevice->CreateRasterizerState(&rdc, &pIr);
    g_pDeviceContext->RSSetState(pIr);

    //アソシエーション
    HRESULT hr;
    IDXGIFactory* pfac = nullptr;
    hr = g_pSwapChain->GetParent(__uuidof(IDXGIFactory), (void**)&pfac);
    // Alt+Enterでの最大化を無効にする設定をする。
    pfac->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);
    SAFE_RELEASE(pIr);
}
void render() {
    //画面クリア(実際は単色で画面を塗りつぶす処理)
    float ClearColor[4] = { 0,0,1,1 };// クリア色作成 RGBAの順
    g_pDeviceContext->ClearRenderTargetView(g_pRenderTargetView, ClearColor);//画面クリア
    g_pDeviceContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);//深度バッファクリア

    g_pSwapChain->Present(0, 0);//画面更新(バックバッファをフロントバッファに
}
void cleanup() {
    SAFE_RELEASE(g_pDepthStencil);
    SAFE_RELEASE(g_pDepthStencilView);
    SAFE_RELEASE(g_pRenderTargetView);
    SAFE_RELEASE(g_pDeviceContext);
    SAFE_RELEASE(g_pSwapChain);
    SAFE_RELEASE(g_pDevice);
}

LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_KEYUP:
        switch (wParam) {
        case VK_ESCAPE:
            PostQuitMessage(0);
            //DestroyWindow(hWnd);
        }
        break;
    case WM_CLOSE:
        PostQuitMessage(0);
        //DestroyWindow(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

const wchar_t* cg_name = L"DX11Sample";
int	_stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpszCmdLine, int iCmdShow)
{
    // ウィンドウクラス初期化
    WNDCLASSEXW wcex =
    {
        sizeof(WNDCLASSEX),
        CS_HREDRAW | CS_VREDRAW,
        (WNDPROC)WndProc,
        0, 0,
        hInstance,
        NULL, NULL,
        (HBRUSH)GetStockObject(WHITE_BRUSH),
        NULL,
        cg_name,
        NULL
    };
    if (!RegisterClassEx(&wcex)) { return 0; }

    RECT clientRect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
    AdjustWindowRect(&clientRect, WS_OVERLAPPEDWINDOW, FALSE);

    HWND hwnd = CreateWindowExW(NULL, cg_name, cg_name,
                                WS_OVERLAPPEDWINDOW,
                                CW_USEDEFAULT, 0,
                                clientRect.right - clientRect.left,
                                clientRect.bottom - clientRect.top,
                                NULL, NULL, hInstance, NULL);
    if (!hwnd) { return 0; }

    // D3D初期化
    initD3D11(hwnd);

    ShowWindow(hwnd, iCmdShow);

    // メッセージループ
    MSG msg;
    do {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else {
            // Direct3Dの処理
            render();
        }
    } while (msg.message != WM_QUIT);

    cleanup();

    return 0;
}
x86/Debug設定で実行時、該当部分の出力は下記のようになります。
D3D11 WARNING: Process is terminating. Using simple reporting. Please call ReportLiveObjects() at runtime for standard reporting. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Producer at 0x00FB23F4, Refcount: 14. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02CFE1F8, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C5D0E8, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C5FFDC, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C60464, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C6060C, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C607BC, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C60964, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C60B18, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C6137C, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02CC85C4, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C90ADC, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02D12034, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C90DF4, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02CE6308, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02CC8B7C, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02CCE344, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C3179C, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C31A84, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C31C2C, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C96E3C, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C9CCB4, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02C9CEAC, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02CA6694, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02CA7B34, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02CBA664, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02CBAF8C, Refcount: 2. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object at 0x02D109DC, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live Object : 27 [ STATE_CREATION WARNING #0: UNKNOWN]
DXGI WARNING: Live Producer at 0x00F8A004, Refcount: 5. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live Object at 0x00F92BA0, Refcount: 3. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live Object : 1 [ STATE_CREATION WARNING #0: ]

コードのどこに問題点があるか、あるいはDirectXSDKインストールの他に必要な設定があるか等
ご存知でしたら教えて頂けますと助かります。

どうぞよろしくお願い致します。


島砂糖

Re: Windows10上でDirect3D11使用時に発生するリークについて

#3

投稿記事 by 島砂糖 » 8年前

Math様

msdnフォーラム記事のご紹介ありがとうございます。

コードの見直しを行ったのですが、開放処理は走っていました。
また上にも記載の点ですが、Windows7で今一度
同じコードを動かしたところ、やはり開放漏れは発生しませんでした。

コード内直接問題となっている箇所、あるいは
Windows10で必要な処理(define等)等分かるととありがたいです。

みえ

Re: Windows10上でDirect3D11使用時に発生するリークについて

#4

投稿記事 by みえ » 8年前

上記サンプルコードを手元の環境 (VS2015, Win10 1607 64bit) でビルドし、32bit の exe を同じ開発環境で実行したところ、リークしたのは 1 つだけでした。

コード:

DXGI WARNING: Process is terminating. Using simple reporting. Please call ReportLiveObjects() at runtime for standard reporting. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live Producer at 0x00B059B4, Refcount: 2. [ STATE_CREATION WARNING #0: ]
ここでリークしていたのは CDXGIFactory でした。そこでコードを見ると、91 行目で取得した pfac がリリースされないようです。94 と 95 行目の間に SAFE_RELEASE(pfac); を入れたところ、リークは直りました。島砂糖さんの実行結果とリークしているオブジェクトの数が異なる理由についてはちょっと分かりません。OS バージョンによって挙動が異なる可能性はありますね。まずはpfac を開放する行を追加した上で結果がどうなるか見ていただけますか。

ちょっとした tips ですが、COM オブジェクトを扱う場合には、SAFE_RELEASE のようなマクロを使う代わりに <atlbase.h> をインクルードして CComPtr や CComQIPtr テンプレートを使うと便利です。エラー処理も含めて、サンプルを書き直してみました。私の環境ではリークは起きません。

コード:

#include <windows.h>
#include <d3d11.h>
#include <atlbase.h>
#include <strsafe.h>

#define WINDOW_WIDTH  200
#define WINDOW_HEIGHT 200

CComPtr<ID3D11Device> g_pDevice;
CComPtr<ID3D11DeviceContext> g_pDeviceContext;
CComPtr<IDXGISwapChain> g_pSwapChain;
CComPtr<ID3D11RenderTargetView> g_pRenderTargetView;
CComPtr<ID3D11DepthStencilView> g_pDepthStencilView;
CComPtr<ID3D11Texture2D> g_pDepthStencil;

void LogDebug(LPCWSTR fmt, ...) {
    WCHAR msg[2048];
    va_list args;
    va_start(args, fmt);
    if (SUCCEEDED(StringCbVPrintf(msg, sizeof(msg), fmt, args))) {
        OutputDebugString(msg);
    }
    va_end(args);
}

#if defined(DEBUG) || defined(_DEBUG)
// デバッグコンパイルの場合、デバッグレイヤーを有効にする。
// ソフトウェア レイヤー
UINT createDeviceFlag = D3D11_CREATE_DEVICE_DEBUG;
#else
UINT createDeviceFlag = 0;
#endif

HRESULT initD3D11(HWND hwnd){
    HRESULT hr;
    CComPtr<ID3D11Texture2D> pBackBuffer;
    CComPtr<ID3D11RasterizerState> pIr;
    CComPtr<IDXGIFactory> pfac;

    // デバイス・スワップチェイン作成
    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory(&sd, sizeof(sd));
    sd.BufferCount = 1;
    sd.BufferDesc.Width = WINDOW_WIDTH;
    sd.BufferDesc.Height = WINDOW_HEIGHT;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = hwnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;

    D3D_FEATURE_LEVEL featureLevels[] = {D3D_FEATURE_LEVEL_11_0};
    D3D_FEATURE_LEVEL actualFeatureLevel;
    hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
        createDeviceFlag, featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pDevice,
        &actualFeatureLevel, &g_pDeviceContext);
    if (FAILED(hr)) {
        LogDebug(L"D3D11CreateDeviceAndSwapChain failed - %08x\n", hr);
        goto exit;
    }

    //レンダーターゲットビューの作成
    hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
    if (FAILED(hr)) {
        LogDebug(L"IDXGISwapChain::GetBuffer failed - %08x\n", hr);
        goto exit;
    }
    hr = g_pDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView);
    if (FAILED(hr)) {
        LogDebug(L"ID3D11Device::CreateRenderTargetView failed - %08x\n", hr);
        goto exit;
    }

    //深度ステンシルビューの作成
    D3D11_TEXTURE2D_DESC descDepth;
    ZeroMemory(&descDepth, sizeof(descDepth));
    descDepth.Width = WINDOW_WIDTH;
    descDepth.Height = WINDOW_HEIGHT;
    descDepth.MipLevels = 1;
    descDepth.ArraySize = 1;
    descDepth.Format = DXGI_FORMAT_D32_FLOAT;
    descDepth.SampleDesc.Count = 1;
    descDepth.SampleDesc.Quality = 0;
    descDepth.Usage = D3D11_USAGE_DEFAULT;
    descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    descDepth.CPUAccessFlags = 0;
    descDepth.MiscFlags = 0;
    hr = g_pDevice->CreateTexture2D(&descDepth, nullptr, &g_pDepthStencil);
    if (FAILED(hr)) {
        LogDebug(L"ID3D11Device::CreateTexture2D failed - %08x\n", hr);
        goto exit;
    }
    hr = g_pDevice->CreateDepthStencilView(g_pDepthStencil, nullptr, &g_pDepthStencilView);
    if (FAILED(hr)) {
        LogDebug(L"ID3D11Device::CreateDepthStencilView failed - %08x\n", hr);
        goto exit;
    }

    //レンダーターゲットビューと深度ステンシルビューをパイプラインにバインド
    ID3D11RenderTargetView * const targetViews[] = {g_pRenderTargetView};
    g_pDeviceContext->OMSetRenderTargets(ARRAYSIZE(targetViews), targetViews, g_pDepthStencilView);

    //ビューポートの設定
    D3D11_VIEWPORT vp;
    ZeroMemory(&vp, sizeof(vp));
    vp.Width = WINDOW_WIDTH;
    vp.Height = WINDOW_HEIGHT;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    g_pDeviceContext->RSSetViewports(1, &vp);

    //ラスタライズ設定
    D3D11_RASTERIZER_DESC rdc;
    ZeroMemory(&rdc, sizeof(rdc));
    rdc.CullMode = D3D11_CULL_NONE;
    rdc.FillMode = D3D11_FILL_SOLID;
    hr = g_pDevice->CreateRasterizerState(&rdc, &pIr);
    if (FAILED(hr)) {
        LogDebug(L"ID3D11Device::CreateRasterizerState failed - %08x\n", hr);
        goto exit;
    }
    g_pDeviceContext->RSSetState(pIr);

    //アソシエーション
    hr = g_pSwapChain->GetParent(__uuidof(IDXGIFactory), (void**)&pfac);
    if (FAILED(hr)) {
        LogDebug(L"IDXGISwapChain::GetParent failed - %08x\n", hr);
        goto exit;
    }

    // Alt+Enterでの最大化を無効にする設定をする。
    hr = pfac->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);
    if (FAILED(hr)) {
        LogDebug(L"IDXGIFactory::MakeWindowAssociation failed - %08x\n", hr);
        goto exit;
    }

exit:
    return hr;
}

HRESULT render() {
    HRESULT hr;

    //画面クリア(実際は単色で画面を塗りつぶす処理)
    float ClearColor[4] = { 0,0,1,1 };// クリア色作成 RGBAの順
    g_pDeviceContext->ClearRenderTargetView(g_pRenderTargetView, ClearColor);//画面クリア
    g_pDeviceContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);//深度バッファクリア

    hr = g_pSwapChain->Present(0, 0);//画面更新(バックバッファをフロントバッファに
    if (FAILED(hr)) {
        LogDebug(L"IDXGISwapChain::GetParent failed - %08x\n", hr);
    }

    return hr;
}

LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_KEYUP:
        switch (wParam) {
        case VK_ESCAPE:
            PostQuitMessage(0);
            //DestroyWindow(hWnd);
        }
        break;
    case WM_CLOSE:
        PostQuitMessage(0);
        //DestroyWindow(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

const wchar_t* cg_name = L"DX11Sample";
int _stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpszCmdLine, int iCmdShow)
{
    // ウィンドウクラス初期化
    WNDCLASSEXW wcex =
    {
        sizeof(WNDCLASSEX),
        CS_HREDRAW | CS_VREDRAW,
        (WNDPROC)WndProc,
        0, 0,
        hInstance,
        nullptr, nullptr,
        (HBRUSH)GetStockObject(WHITE_BRUSH),
        nullptr,
        cg_name,
        nullptr
    };
    if (!RegisterClassEx(&wcex)) { return 0; }

    RECT clientRect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
    AdjustWindowRect(&clientRect, WS_OVERLAPPEDWINDOW, FALSE);

    HWND hwnd = CreateWindowExW(0, cg_name, cg_name,
                                WS_OVERLAPPEDWINDOW,
                                CW_USEDEFAULT, 0,
                                clientRect.right - clientRect.left,
                                clientRect.bottom - clientRect.top,
                                nullptr, nullptr, hInstance, nullptr);
    if (!hwnd) { return 0; }

    // D3D初期化
    if (SUCCEEDED(initD3D11(hwnd))) {
        ShowWindow(hwnd, iCmdShow);

        // メッセージループ
        MSG msg;
        do {
            if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else {
                // Direct3Dの処理
                render();
            }
        } while (msg.message != WM_QUIT);
    }

    return 0;
}

Math

Re: Windows10上でDirect3D11使用時に発生するリークについて

#5

投稿記事 by Math » 8年前

DirestX10以降DirectX9にくらべ格段に難しくなっています。プロでも難しいといわれています。
マイクロソフトのMSDNに質問されるのがよいでしょう。(COM オブジェクトの解放については特に難しい問題を内包している恐れがあります。)
DirectXがOSに採用されてから情報がすくなくなりもともと最先端の技術を取り入れているためVersion格差もありマイクロソフトでなければ把握出来ないとおもわれます。マイクロソフトには情報が相当集まっているようです。環境依存についても彼等はテスト出来るだけのものを持っています。(DirestX12では大きな変化がありました)

島砂糖

Re: Windows10上でDirect3D11使用時に発生するリークについて

#6

投稿記事 by 島砂糖 » 8年前

みえ様、Math様

ソースを作って頂き大変ありがとうございます、
Math様にもご指摘頂いている通り、DirectX11では9と比べて必要なインターフェイスが相当量増えているため
COMオブジェクトの参照管理はスマートポインタに任せるのが良さそうです。
9までは直にオブジェクトを触っていましたが、11で扱うインターフェイスが相当増えているため
ソース管理含めてやり方を見直さないといけませんね…

ただ、こちらでd3d11.libを使うようにして改めてビルドしたところ、
やはり開放漏れが発生しました。上にWindows7で発生しないと記載致しましたが、
どうやらWindows10のこのPCでのみ発生しているようです。
開発環境かsystem32以下の構成がおかしいのかも知れません。
こちらを確認と再セットアップの上で、もう少し様子を見てみようと思います。

みえ
記事: 23
登録日時: 8年前

Re: Windows10上でDirect3D11使用時に発生するリークについて

#7

投稿記事 by みえ » 8年前

駄目でしたか・・不可解ですね。

私の環境では D3D_FEATURE_LEVEL_11_0 がサポートされていなかったので、代わりに D3D_FEATURE_LEVEL_10_0 を使っています。もしかするとD3D_FEATURE_LEVEL_11_0 ではリークが起きるのかもしれません。
これも可能性は低いですが、DirectX 側 のバグであることも考えられなくはないです。Win10 をお使いとのことですが、もし最新の累積パッチをインストールされていないようでしたら、インストールして結果を見ていただけますか。

直接的には、コード内で使われているオブジェクトのどれが解放されていないのかを地道に調べていくしかないですね。例えば Live Producer というのは IDXGIFactory のことのようですが、島砂糖さん側の出力では 0x00FB23F4 と 0x00F8A004 とで 2 つ存在あるようです。1 つは pfac として、もう一つがどこで作られたものなのかが気になります。

あまりお役に立てず申し訳ないですが、もし何か進展があれば返信いただけると幸いです。

島砂糖

Re: Windows10上でDirect3D11使用時に発生するリークについて

#8

投稿記事 by 島砂糖 » 8年前

OSからクリーンインストールの上、再構築したところリークが発生しなくなりました。
やはり環境に問題があったようです。
調べても全く似た事例が見つからなかったためもしかしてと思っていましたが、
こちらが原因と考えればそれも納得がいきます。

Math様も情報のご提供ありがとうございます、
コーディング上のミスやOSの違いによる挙動の違いがあることを考え、
やはりCOMの参照カウンタを直に弄るよりも安全な方法となるよう
手持ちのコードもメンテナンスをしていきたいと思います。

元々のコード、みえ様よりご提示頂いたコードの実行結果ともに
みえ様の結果と同様となりましたので、解決とさせてい頂きます。

大変ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る