COM smart pointer question

Started by
4 comments, last by s_p_oneil 19 years, 7 months ago
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?
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));
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
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.
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 ;)
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.
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.

This topic is closed to new replies.

Advertisement