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.
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.