首页 > 解决方案 > WRL::ComPtr 导致 d3d 中的对象泄漏?

问题描述

我正在制作一个简单的 d3d 11 应用程序,并且正在使用 Microsoft::WRL::ComPtr 自动释放资源。出于某种原因,当应用程序退出时,我从 d3d 收到了 30-40 个 Live Object 警告。我可能会错过一两个,但这似乎更像是我拥有的所有对象的计数。我显然做错了什么。我的一般用法是在某个包装类中有一个成员:

class graphics_device
{
   // ...
   ComPtr<ID3D11Device> hwdevice;
}

理论上应该在类销毁时释放对象。(我在堆栈上创建了大多数对象,并且我仔细检查了我是否删除了堆上的对象)

当我创建我的功能时,我将它们作为参考传递。例如:

void graphics_device::create_constant_buffer(u32 size, const void* data, ComPtr<ID3D11Buffer>& constantBuffer)
{
    D3D11_BUFFER_DESC bufferDesc;
    ZeroMemory(&bufferDesc, sizeof(bufferDesc));

    bufferDesc.Usage = D3D11_USAGE_DEFAULT;
    bufferDesc.ByteWidth = size;
    bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    bufferDesc.CPUAccessFlags = 0;

    D3D11_SUBRESOURCE_DATA initData;
    ZeroMemory(&initData, sizeof(initData));
    initData.pSysMem = data;

    device->CreateBuffer(&bufferDesc, &initData, &constantBuffer);
}

有什么我想念的想法吗?

编辑:忘记发布来自 d3d11 的警告:

D3D11 WARNING:  Live Object at 0x0061D93C, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING:  Live Object at 0x0061DBE4, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING:  Live Object at 0x0061DE8C, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D11 WARNING: Live                         Object :     31 [ STATE_CREATION WARNING #0: UNKNOWN]
DXGI WARNING: Live Producer at 0x005ADDC0, Refcount: 4. [ STATE_CREATION WARNING #0: ]
DXGI WARNING:   Live Object at 0x005B7FD0, Refcount: 2. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live                         Object :      1 [ STATE_CREATION WARNING #0: ]

还有更多类似的。在运行时我没有收到任何其他警告。

标签: c++comdirect3d11

解决方案


获得一个“干净的出口”可能有点挑战。ComPtr如果使用正确,则不太可能。根据评论,一个好的起点是对象命名。请记住,输出发生在 Direct3D 设备被释放时,因此您可能需要查看“释放顺序”以使其干净地退出。还有“内部”与“外部”参考计数,因此它们可能会有些混乱。有关调试层使用的一些说明,请参阅此博客文章

要记住的另一件事是 Direct3D 对象报告不能真正告诉您 DXGI 拥有的对象。这就是为什么使用DXGI 调试设备也很有用的原因。

directx-vs-templates将这些博客文章中的所有建议放在一个地方,因此您可能需要查看它们。

最后,ComPtr即使通过引用,作为参数传递通常也不是最佳用例。ComPtr用作数据成员和局部变量很好,但通常作为参数最好使用“原始指针”,因为生命周期已经是隐式的。所以你的函数签名会更好:

void graphics_device::create_constant_buffer(u32 size, const void* data, ID3D11Buffer** constantBuffer);

然后在调用该函数时,您使用ComPtr

ComPtr<ID3D11Buffer> cb;
graphicsdevice->create_constant_buffer(size, data, &cb);

有关最有效地使用它的一些提示,请参阅ComPtr 上的这个 wiki 。


推荐阅读