Vlad Serhiienko
Vlad Serhiienko

Reputation: 113

Failed to release Direct3D Device "or" Corresponding Context

Yes, its actually "or". I shall explain. I am developing helper classes for myself, like DirectXToolKit. For managing COMs I`m using Microsoft::WRL::ComPtr<T> (wrl.h).

struct Renderer
{
    ComPtr<ID3D11Device> m_Device;
    ComPtr<ID3D11DeviceContext> m_ImmContext;
}

When all the resources are destroyed, the instance of the structure above should be destroyed as well, but after the dtor is called, I am triggering the error in Microsoft::WRL::ComPtr<T>, when it tries to release the device or context.

I have implemented the dtor where I manually release m_Device and m_ImmContext, but unfortunately the last member I try to release always encounters an issue in the function

unsigned long InternalRelease() throw()
{
    unsigned long ref = 0;
    T* temp = ptr_;

    if (temp != nullptr)
    {
        ptr_ = nullptr;
        ref = temp->Release();
    }

    return ref;
}

here

ref = temp->Release();

When I succeed releasing the device first, the context triggers the error, and vice versa (! yes, when one of them was successfully released, the destuction of the second member fails). There was already a question like mine (destroy directx device and swap chain), but the window and swapchain are already destroyed, like the other dx resources. Have no clue why is this happening. Any ideas?

Sorry for my imperfect English :3

Upvotes: 5

Views: 1098

Answers (2)

Vlad Serhiienko
Vlad Serhiienko

Reputation: 113

I have fixed this issue. The problem was I have not understood std::shared_ptr good enough (the function std::make_shared actually (about shared pointers and their allocation)):

I have created the pointer like:

Obj *ObjPtr = new Obj();

and then just:

SomeOtherState.SharedObj = std::make_shared<Obj>(*ObjPtr);

and didn`t destroy the ObjPtr afterwards. The data ObjPtr was pointing on was still in memory, after SomeOtherState was destroyed (and as far as I have understood the issue should have gone as well if I have used the std::shared_ptr ctor) .

Most likely it was because of this memory leak, but there was another thing I have changed: CoUninitialize call was made before the last COM pointer was destroyed but from MSDN: CoUninitialize came that its important (from the first para actually):

Closes the COM library on the current thread, unloads all DLLs loaded by the thread, frees any other resources that the thread maintains, and forces all RPC connections on the thread to close.

So I have replaced CoInitialize and CoUninitialize correspondently and the issue have gone. If someone had had the same troubles, this could somewhat be a solution (either or both the first and the second change I have made).

I should probably add "com" tags for my question

Upvotes: 3

Rostislav Stribrny
Rostislav Stribrny

Reputation: 157

the problem MAY be somewhere when you obtain the ImmediateContext. According to the documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/ff476529%28v=vs.85%29.aspx

The GetImmediateContext method increments the reference count of the immediate
context by one. Therefore, you must call Release on the returned interface pointer
when you are done with it to avoid a memory leak. 

So I >>>guess<<< that you've forgot releasing the context somewhere so the Device release fails afterwards.

BTW: Make also sure that resources are ALWAYS released in reverse order.

Upvotes: 0

Related Questions