Я работаю с d3d11 уже довольно давно, и после обнаружения отладчика DirectX я недавно обнаружил, что моя программа повсюду пропускает память из-за всех com-объектов, которые не освобождаются должным образом. После небольшого поиска и нескольких часов изучения кода я разработал несколько методов, чтобы изолировать, где я получаю эти неожиданные увеличения счетчиков ссылок.
во-первых, все объекты обернуты в std::shared_ptrs с пользовательскими удалениями, которые вызывают соответствующие функции освобождения. Я сделал это, чтобы мне никогда не приходилось вызывать addref, а первый вызов для освобождения, тот, что в средстве удаления, вызывался только тогда, когда объект выходил за пределы области видимости. Это будет выглядеть примерно так:
// 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 стал владельцем), количество незавершенных ссылок уже равно 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-объекты. Есть ли такой способ, которым я могу просто вручную удалить их, а не использовать закулисную ерунду подсчета ссылок?