私はかなり長い間 d3d11 を使用してきましたが、directx デバッガーを発見した後、最近、私のプログラムが適切に解放されていないすべての com オブジェクトからメモリをリークしていることを発見しました。少しスヌーピングし、何時間もコードを見つめた後、これらの予期しない参照カウントの増加が発生している場所を特定する方法をいくつか開発しました。
まず、すべてのオブジェクトが std::shared_ptrs にラップされ、それぞれのリリース関数を呼び出すカスタム デリーターが含まれています。これを行ったのは、addref を呼び出す必要がないようにするためであり、オブジェクトがスコープ外になったときにのみ、deleter 内の release への最初の呼び出しが呼び出されるようにしました。次のようになります。
// in D3D11Renderer.h
...
// declaration
std::shared_ptr<ID3D11Device *> m_Device;
...
// after call to ID3D11CreateDeviceAndSwapChain
m_Device.reset(device, [](ID3D11Device * ptr){ptr->Release();})
問題は、API呼び出しの特定のランダム関数が参照カウントをランダムに増加させるだけで、後で対処する必要があることです。
私が診断に役立つと思ったのは、次のような関数でした。
template <typename T>
int getRefCount(T object)
{
object->AddRef();
return object->Release();
}
これは、そのカウントをインクリメントおよびデクリメントして、そのオブジェクトの現在の参照数を取得します。これを使用して、カスタム デリーターのリリースが呼び出される直前に、作成した 1 つの ID3D11Device への未解決の参照が 10 個あることがわかりました。不思議なことに、私はゆっくりとバックトラックし、最初に作成した場所まで、プログラムをずっとさかのぼってこの関数を呼び出しました。面白いことに、最初にオブジェクトを作成した直後 (shared_ptr が所有権を取得する前であっても)、未処理の参照の数はすでに 3 です! これは、この直後に発生します。
result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1,
D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, NULL, &deviceContext);
if(FAILED(result))
{
return false;
}
デバイスを作成するこのような関数を呼び出すのはこれが初めてで、直後に参照がいくつあるかを確認すると、3 と表示されます。明らかに、これらの com オブジェクトの処理方法について、私は何かを誤解しています。ナンセンスをカウントする舞台裏の参照を使用するのではなく、手動でそれらを削除できる方法はありますか?