Search code examples
c++comwrl

Reference count of ComPtr returned from a factory method is incremented twice


I declared a COM interface and I have two implementations(classes) of the interface depending on input config. I also have a factory method that checks for input config and appropriately calls NEW on the class. In my class I implement AddRef() and Release() as per COM spec. I declare a ComPtr and call the factory method to get access to above interface. I can do this two ways,

1) Return ComPtr from Factory method

ComPtr<ICaptureSource> ICaptureSource::CreateInstance(someConfig)
{
   switch (someConfig)
   {
     case 1:
          return (new CCaptureSource1());  >> Ref count in this class is initialized to 1 
          break;
     case 2:
          return (new CCaptureSource2());  >> Ref count in this class is initialized to 1 
           break;
     default:
          return nullptr;
   }

}


ComPtr <ICaptureSource> captureSource;

captureSource = ICaptureSource::CreateInstance(someConfig);

After returning from above call, Ref count of captureSource is '2'. I was expecting it to be 1.

However with below code, Ref count is 1

2) Pass ComPtr address as parameter to factory method

HRESULT ICaptureSource::CreateInstance(someConfig, ICapturesource **ppv)
{
   ICaptureSource *pTemp = nullptr;
   switch (someConfig)
   {
     case 1:
          pTemp = new CCaptureSource1();  >> Ref count in this class is initialized to 1 
          break;
     case 2:
          pTemp = new CCaptureSource2();  >> Ref count in this class is initialized to 1 
           break;
   }

  if (SUCCEEDED(hr) && (ppv != nullptr))
  {
     *ppv = pTemp;
  }
  return hr
}

ComPtr <ICaptureSource> captureSource;

hr = ICaptureSource::CreateInstance(someConfig, &captureSource);

captureSource ref count is now 1.

Kindly guide me why is there a difference in ref count in above two approaches and why returning an object is incrementing ref count (2), Vs setting object pointer to *ppv (ref count 1).

As it can be expected, approach (1) is causing memleak because ref count does not go to 0.


Solution

  • WRL ComPtr instance is automatically incrementing reference counter at the moment your

    new CCaptureSource1()

    is converted to returned

    ComPtr<ICaptureSource>

    This is behavior by design and as documented ("...automatically maintains a reference count for the underlying interface pointer..."). When your captureSource variable goes out of scope, there will be a reference count decrement on your object.

    In your second approach you are attaching a raw interface pointer into ComPtr instance: you place a raw (meaning: not incremented by smart pointer class) pointer into *ppv so reference counter remains being one. ComPtr instance will have the pointer attached without increment, but it will decrement it on destruction. This is how the reference counter reaches zero.