Jump to content
  • Advertisement
Sign in to follow this  
Fourty_Two

COM smart pointer question

This topic is 5406 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a COM smart pointer class all coded up, but I ran into an interesting senario that I don't know how to handle.
typedef com_ptr<IDirect3D8> DIRECT3D8_PTR;

int main() {
	DIRECT3D8_PTR ptrD3D;
	if(NULL==(ptrD3D=Direct3DCreate8( D3D_SDK_VERSION )))
	{
		cout << "Could not create Direct3D\n";
		return FALSE;
	}

	return 0;
}


Direct3DCreate8 returns a pointer to an IDirect3D8 interface. This should call the operator=() of my com_ptr, which it does. However, the operator=() calls AddRef on the object, making its reference count 2, like it should if you where making a copy of a COM object pointer, but ptrD3D is the only owner of the object, so I get a memory leak error. Is there anyway to get around this?

Share this post


Link to post
Share on other sites
Advertisement
You can look at CComPtr which the MS supplied COM smart pointer and see what they do.

You can provide access to the raw pointer, that assignments such as that one should use (I think that's how CComPtr works).

Or you could add a reset method like std::auto_ptr and the boost smart pointers.

d3d.reset(Direct3DCreate8(D3D_SDK_VERSION));

Share this post


Link to post
Share on other sites
Quote:
Original post by Fourty_Two
Direct3DCreate8 returns a pointer to an IDirect3D8 interface. This should call the operator=() of my com_ptr, which it does. However, the operator=() calls AddRef on the object, making its reference count 2, ...


Maybe you should change your code to:

DIRECT3D8_PTR ptrD3D(Direct3DCreate8( D3D_SDK_VERSION ));
if(NULL==ptrD3D) ...


Define the constructor to be explicit and don't call AddRef in the ctor.

Share this post


Link to post
Share on other sites
Heh, my code is almost identical to the CComPtr class. As for the operator in question, it is identical. They do the same combination of AddRef(), Release(), assignment that I do.

nmi:

I've done just that to fix the problem, but it seems that there is some violation of COM going on for this problem to exist. I also just used my existing code and changed the variable type ;)

Share this post


Link to post
Share on other sites
Actually, nmi, that won't work now that I think about it. There isn't any difference between the internals of the copy constuctor and the assignment.

Share this post


Link to post
Share on other sites
There are a number of ways to deal with this type of problem:

1) Many smart pointer classes also have Attach() and Detach() methods, which set and clear it without calling AddRef() or Release(). This would be the best method in your specific case.

2) Many smart pointer classes override the & operator to return a direct pointer to the interface pointer. This allows global functions like CoCreateInstance(&ptr) and QueryInterface(&ptr) to set it directly. In your case, you could use "*(&ptr) = ". It's not as clean as ptr.Attach(), but it will work.

3) Some smart pointer classes have a way to call the Create/QueryInterface method in their constructor. For instance, the CComQIPtr<> automatically calls QueryInterface(), so it doesn't need to call AddRef(). You could derive a custom smart pointer class to handle Direct3DCreate(), but it's probably not worth it unless you want to add other helper functions to this custom class, make it a singleton, or do something else custom with it.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!