D3D11从哪里增加了引用计数? [英] D3D11 increased ref count from nowhere?

查看:83
本文介绍了D3D11从哪里增加了引用计数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用d3d11已有很长时间了,发现DirectX调试器后,我最近发现我的程序正在从所有无法正常释放的com对象到处泄漏内存.经过一番窥探和盯着代码看了几个小时,我开发了一些方法来隔离导致引用计数意外增加的地方.

I have been working with d3d11 for quite a while now, and after discovering the directx debugger, i've recently discovered that my program is leaking memory everywhere from all the com objects that aren't releasing properly. After a bit of snooping around and hours of staring at the code, i've developed some methods to isolate where i'm getting these unexpected increases to the ref counts.

首先,所有对象都被带有自定义删除器的std :: shared_ptrs包裹,这些删除器调用各自的发布函数.我这样做是因为我永远不必调用addref,并且只有在对象超出范围时才调用释放的第一个调用,即删除程序中的调用.看起来像这样:

first off, all of the objects are wrapped in std::shared_ptrs with custom deleters that call their respective release function. I did this so i would never have to call addref, and the first call to release, the one in the deleter, would only be called when the object went out of scope. It would look something like this:

// in D3D11Renderer.h
...
// declaration
std::shared_ptr<ID3D11Device *> m_Device;
...

// after call to ID3D11CreateDeviceAndSwapChain
m_Device.reset(device, [](ID3D11Device * ptr){ptr->Release();})

问题是api调用中的某些随机函数只会随机增加引用计数,希望我稍后再处理.

Problem is certain random functions in the api calls will just randomly increase the ref count, expecting me to have to deal with it later.

我发现对诊断有用的功能是这样的:

something i found useful in diagnosis was a function that looked like this:

template <typename T>
int getRefCount(T object) 
{
    object->AddRef();
    return object->Release();
}

,只需递增和递减计数即可获得该对象上当前引用的计数.使用此工具,我发现,在调用自定义删除程序中的发布之前,有10个未完成的引用创建了我创建的1个ID3D11Device.很好奇,我慢慢地回溯了,直到从我最初创建它的地方,一直在程序中一直调用此函数.有趣的是,在我第一次创建对象之后(甚至在shared_ptr取得所有权之前),未完成引用的数量已经是3!这是在此之后立即发生的.

which, just increments and decrements that count to obtain the current count of refs on that object. Using this, i found that, just before the release in the custom deleter is called, there are 10 outstanding references to the 1 ID3D11Device i created. Curious, i backtracked slowly, calling this function all the way back through the program, right up to where i originally created it. Funny thing, just after i first create the object, (even before the shared_ptr takes ownership), the number of outstanding refs is already 3! This occurs immediately after this here.

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对象应该被处理的方式误解了.有什么方法可以手动删除它们,然后在后台使用引用计数来胡说八道?

this is the first time i call any such function that creates the device, and when i check to see how many refs there are right after, and it says 3! So clearly, I'm misunderstanding something about the way these com objects are supposed to be handled. Is there any such way that i can just manually delete them, rather then use there behind-the-scenes ref counting nonsense?

推荐答案

每次创建缓冲区或着色器或任何依赖于设备的内容时,该对象都可能包含对设备的引用,因此会增加对它的引用计数以确保它在使用时不会被删除.

Every time you create a buffer or a shader or anything that depends on the device, that object will likely contain a reference to the device so will bump up it's reference count to ensure it's not deleted while it is still using it.

听起来您的方法可能总体上很好,因为您将在代码中保留一个对设备的单一引用,以防止设备被删除,而当所有内部引用都消失时,则将其释放.但是d3d仍将执行其自己的引用计数,因此当您释放对所有其他相关对象的每个引用时,引用计数将仅降至零.即使只是创建交换链和设备也将创建后缓冲区,以此类推,可能需要维护对设备的引用.

It sounds like your approach might well work overall, as you'll essentially keep one single reference to the device in your code to stop it being deleted, and when all your internal references are gone release it. However d3d will still be doing it's own reference counting and so the reference count will only drop to zero when you release every reference to every other related object. Even just creating the swap chain and device will make back buffers and so on that likely need to maintain a reference to the device.

我尝试了同样的想法一段时间……最后发现

I tried this same idea for a while... And in the end found it much easier to just

#include <atlbase>

然后使用

CComPtr<ID311Device> m_Device

因为这几乎是该类设计的目的,并且比std :: shader_ptr更轻巧,因为对象中已经有一个引用计数器,因此无需保留单独的引用.

as that's pretty much exactly what that class is designed for and it's more lightweight than std::shader_ptr as the objects already have a reference counter in them so there is no need to keep a separate one.

这篇关于D3D11从哪里增加了引用计数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆