Sign in to follow this  
cozzie

Push_back raw pointer as COM pointer? (inputlayout)

Recommended Posts

Hi,

I'm struggling with adding 'raw pointers' as CComPtr in a std::vector, without memory leaks.

To illustrate:

 

- GetInputLayout returns a ID3D11InputLayout* (raw pointer)

- the mInputLayouts is a std::vector<CComPtr<ID3D11InputLayout>>

 

This code works without memory leaks from D3D (ref counts, no release() issues):

	ID3D11InputLayout *newLayout = mFallbackPack.GetInputLayout(pDevice);
	mInputLayouts.emplace_back();
	mInputLayouts.back() = newLayout;
	ReleaseCOM(newLayout);

When I do it 'directly', I get REF count issues with D3D (leaks):

	mInputLayouts.push_back(mFallbackPack.GetInputLayout(pDevice));

I can explain that the 2nd option gives a leak, because I'm trying to add a RAW pointer in a std::vector with CComPtr's.

 

Question: is there an easier way to achieve what I want? (without 4 lines of code)

Any input/ thoughts are appreciated.

Share this post


Link to post
Share on other sites

Why does GetInputLayout return a raw pointer? Does it AddRef before it returns the object?

 

For what it's worth, the typical pattern with COM is that returning a pointer is a "weak" pointer, which has not had a reference added to it yet, where a "strong" pointer is returned by out parameter, so you can pass in the address of a CComPtr. Consider making GetInputLayout behave this way. Then you can do:

mInputLayouts.push_back();
mFallbackPack.GetInputLayout(pDevice, &mInputLayouts.back());

If you're on C++17, it looks emplace_back returns a reference, so you could just do:

mFallbackPack.GetInputLayout(pDevice, &mInputLayouts.emplace_back());

Or if you make mFallbackPack return a CComPtr or CComPtr&, then you don't need to manually ReleaseCOM.

Share this post


Link to post
Share on other sites

Oh, and there's also the Attach method which doesn't AddRef while taking ownership. So if you still want to return a raw "strong" pointer, you can do:

mInputLayouts.emplace_back(CComPtr<ID3D11InputLayout>().Attach(mFallbackPack.GetInputLayout(pDevice)));
Edited by Jesse Natalie

Share this post


Link to post
Share on other sites

I'd say both code snippets you provided should do the same eventually.

 

newLayout will be released at least twice, once with the direct call and once after it is destructed/overwritten in the vector.

 

How about GetInputLayout() simply keeps and returns a ComPtr itself? This way its also clear who should perform the cleaning.

Share this post


Link to post
Share on other sites

Thanks both. I've been trying out the different options.

But without having GetInputLayout return a CComPtr I could find a way that worked by assigning it directly, like this:

mInputLayouts.emplace_back(CComPtr<ID3D11InputLayout>().Attach(mFallbackPack.GetInputLayout(pDevice)));

This gives the following compiler error:

>e:\projects\crealysm11\crealysm11\d3drenderer\cd3dshadermanager.cpp(176): error C2672: 'std::vector<ATL::CComPtr<ID3D11InputLayout>,std::allocator<_Ty>>::emplace_back': no matching overloaded function found
1>          with
1>          [
1>              _Ty=ATL::CComPtr<ID3D11InputLayout>
1>          ]
1>e:\projects\crealysm11\crealysm11\d3drenderer\cd3dshadermanager.cpp(176): error C2893: Failed to specialize function template 'void std::vector<ATL::CComPtr<ID3D11InputLayout>,std::allocator<_Ty>>::emplace_back(_Valty &&...)'
1>          with
1>          [
1>              _Ty=ATL::CComPtr<ID3D11InputLayout>
1>          ]
1>  e:\projects\crealysm11\crealysm11\d3drenderer\cd3dshadermanager.cpp(176): note: With the following template arguments:
1>  e:\projects\crealysm11\crealysm11\d3drenderer\cd3dshadermanager.cpp(176): note: '_Valty={void}'

Since I'm not aiming/ using C++ 17, I think I have 3 options:

 

- with the extra step in the middle, which I already got working

- let the GetInputLayout function return a CComPtr

- add an 'out' parameter for the hard pointer, and pass it like reference (like mentioned above).

Share this post


Link to post
Share on other sites

N.p., I've decided to let the GetInputLayout function return a CComPtr, and it works like a charm without leaks.

I also decided to keep to the following guideline;

- if I retrieve a pointer from a class, which is a member of the class, then I return a const mObject const pointer

- when a class member function returns a 'local pointer'/ no member, like the GetInputLayout, I return a CComPtr, to prevent leaks and issues on ownership

(which occured in the initial approach, because the ownership of the raw pointer returned by the GetInputLayout function, was unclear, because I added it to a CComPtr vector).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this