Правильный способ освободить интерфейс COM - PullRequest
0 голосов
/ 25 сентября 2018

У нас есть устаревший программный код, который использует COM.Я заметил, что в одном месте мы выполняем queryInterface для IInspectable указателя, но не беспокоимся о вызове release.

Например:

void foo(IInspectable* myInterface)
{
    ComPtr<OBJTYPE> pObj;
    auto hr = myInterface->QueryInterface(__uuidof(SomeType),&pObj);
    if (hr != S_OK)
    {
        return hr;
    }
    //some code that uses pObj
}

Я добавил Release в приведенный выше код, напримерниже:

auto hr = myInterface->QueryInterface(__uuidof(SomeType),&pObj);
if (hr != S_OK)
{
    return hr;
}
myInterface->Release(); //<-- Is this the correct way to release ?
//some code that uses pObj;

Но я вижу, что приведенный выше код иногда дает сбой в вышеуказанной функции во время выпуска.Что-то не так в том, как я выпускаю интерфейс?Я могу подтвердить, что myInterface не используется где-либо еще в функции после оператора Release.

Извинения за невозможность скопировать / вставить фактический код, но приведенный выше код суммирует в значительной степени подозрительный код, который яотлаживаю.По сути, я хочу знать, нужно ли в приведенном выше сценарии вызывать Release ()?И это правильное место / способ вызова Release ()?Нужно ли добавлять какие-либо другие проверки безопасности на месте?

1 Ответ

0 голосов
/ 25 сентября 2018

В первой функции foo вы НЕ должны вызывать myInterface->Release().Каждый звонок на Release должен сопровождаться добавлением ссылки.В этой функции вы не выполняете myInterface->AddRef, поэтому, если вы добавите myInterface->Release, ваша функция будет уменьшать счетчик ссылок на единицу, что не похоже на правильное поведение.

Концептуально, вы должны вызвать AddRef при входе в функцию и Release при выходе из функции.Несмотря на то, что подсчет ссылок является «навязчивым» в COM, рекомендуемый стиль кодирования состоит в том, чтобы обрабатывать каждый указатель интерфейса так, как будто он имеет свой собственный счетчик ссылок.

Обычно он заключен в классы интеллектуальных указателей.Но при работе с функцией, которая получает необработанный указатель на интерфейс «in», этот Add и Release можно «оптимизировать», просто пропустив оба этих вызова в функции и обработав указатель как указатель наблюдателя.


Вызов QueryInterface будет неявно делать pObj->AddRef(), но это не имеет ничего общего с myInterface.Когда вы закончите с pObj, должно произойти pObj->Release() - но это управляется оболочкой ComPtr, вам не следует добавлять явный вызов.

...