Счетчик ссылок ComPtr, возвращаемый фабричным методом, увеличивается вдвое - PullRequest
0 голосов
/ 04 ноября 2019

Я объявил интерфейс COM, и у меня есть две реализации (классы) интерфейса в зависимости от конфигурации ввода. У меня также есть фабричный метод, который проверяет входную конфигурацию и соответствующим образом вызывает NEW для класса. В моем классе я реализую AddRef() и Release() согласно COM спецификации. Я объявляю ComPtr и вызываю фабричный метод, чтобы получить доступ к вышеуказанному интерфейсу. Я могу сделать это двумя способами,

1) Вернуть ComPtr из метода Factory

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);

После возврата из вышеприведенного вызова счетчик ссылок captureSource равен '2'. Я ожидал, что это будет 1.

Однако с приведенным ниже кодом счетчик ссылок равен 1

2) Передать адрес ComPtr в качестве параметра к заводскому методу

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 счетчик ссылок теперь 1.

Пожалуйста, объясните мне, почему существует разница в количестве ссылок выше двухподходы и почему возвращение объекта увеличивает ref count (2), Vs устанавливает указатель объекта на *ppv (ref count 1).

Как и следовало ожидать, подход (1) вызывает memleak, потому что ref countне идет к 0.

1 Ответ

0 голосов
/ 04 ноября 2019

WRL ComPtr экземпляр автоматически увеличивает счетчик ссылок в тот момент, когда ваш

new CCaptureSource1()

преобразуется в возвращенный

ComPtr<ICaptureSource>

Это поведение разработано и задокументировано («... автоматически поддерживает счетчик ссылок для базового указателя интерфейса ...»). Когда ваша переменная captureSource выйдет из области видимости, для вашего объекта произойдет уменьшение количества ссылок.

Во втором подходе вы присоединяете необработанный указатель интерфейса к экземпляру ComPtr: вы помещаете необработанный (значение: не увеличивается классом указателя) указатель на *ppv, поэтому счетчик ссылок остается единым целым. * У экземпляра ComPtr указатель будет прикреплен без приращения, но он будет уменьшать его при уничтожении. Вот как счетчик ссылок достигает нуля.

...