Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

COM object created by CComObject::CreateInstance not destroyed when pointer goes out of scope

Using smart pointer CComObject I create a COM object by calling its static method CreateInstance. But when I leave my program, at least in VS13, that object remains running. Here is my code:

CComObject< CMyAtlObject > * myAtlCOMObject = NULL;
HRESULT hr = CComObject< CMyAtlObject >::CreateInstance(&myAtlCOMObject);
ASSERT(SUCCEEDED(hr));

I expected the ~CComObject() method to be called when going out of scope which does not happen.

I tried putting the code above in curly braces to force the newly created object to go out scope. I tried calling FinalRelease on myAtlCOMObject and succeeded in manually calling Release on myAtlCOMObject, but the program still didn't stop running in VS13.

What am I missing?

like image 615
rtischer8277 Avatar asked Sep 01 '14 14:09

rtischer8277


1 Answers

Here is the code with inline comments:

{
  CComObject<CMyAtlObject>* myAtlCOMObject = NULL;
  HRESULT hr = CComObject< CMyAtlObject >::CreateInstance(&myAtlCOMObject);
  ASSERT(SUCCEEDED(hr));
  // NOTE: Created new object with reference count of ZERO
  {
    const CComQIPtr<IMyAtlObject> pMyAtlObject = myAtlCOMObject;
    // NOTE: Reference count increased to ONE
  }
  // NOTE: ~CComQIPtr went out of scope and called IUnknown::Release 
  //       decrementing counter to ZERO; decrement to zero causes destruction
}
// NOTE: There is no ~CComObject call here on myAtlCOMObject going out of scope
//       since myAtlCOMObject is a raw pointer

What am I missing?

You are missing the following:

  • CreateInstance creates a new object and gets you raw pointer which is not going to self-destroy on leaving scope
  • CreateInstance creates an object in "unstable" state with refcount of zero, it's self-desrtuction on reference management starts after something increments refcount AT LEAST ONCE and then decrements it to zero; CComQIPtr above is an example of this

MSDN on CreateInstance:

The object returned has a reference count of zero, so call AddRef immediately, then use Release to free the reference on the object pointer when you're done.

What do you use instead of CComObject::CreateInstance?

I have a helper template class CObjectPtr which acts in the way similar to well known CComPtr and wraps/manages native C++ class.

My code would be:

CObjectPtr<CFoo> pFoo;
pFoo.Construct(); // Instantiates automatically adding reference
CFoo* pRawFoo = pFoo; // Acts as a pointer
CComPtr<IFoo> pFooInterface = pFoo; // Good for exposing inmepleted interafaces
CObjectPtr<CFoo> pAnotherFoo = pFoo; // Same instance proper reference counting
// ~CObjectPtr releases reference, destroys the object on last release

Another simple wrapper is also provided in this answer: How to better initialize a reference counter for a non-creatable COM object?.

like image 60
Roman R. Avatar answered Oct 18 '22 14:10

Roman R.