我已经使用 d3d11 有一段时间了,在发现 directx 调试器之后,我最近发现我的程序从所有未正确释放的 com 对象中到处泄漏内存。经过一番窥探和盯着代码几个小时后,我开发了一些方法来隔离引用计数意外增加的位置。
首先,所有对象都被包装在 std::shared_ptrs 中,并带有调用各自释放函数的自定义删除器。我这样做是为了永远不必调用 addref,并且第一次调用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();
}
其中,只需增加和减少计数即可获取该对象的当前引用计数。使用这个,我发现,就在调用自定义删除器中的发布之前,有 10 个对我创建的 1 ID3D11Device 的未完成引用。出于好奇,我慢慢地回溯,在程序中一直调用这个函数,直到我最初创建它的地方。有趣的是,就在我第一次创建对象之后(甚至在shared_ptr取得所有权之前),未完成的refs的数量已经是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 对象的处理方式。有没有什么方法可以让我手动删除它们,而不是使用幕后引用计数废话?