Как мне проверить, можно ли использовать параметры [out] в COM?

Официально не следует использовать параметры [out] из COM-функций, если функция не завершилась успешно. Это означает, что есть (по крайней мере) три способа узнать, можно ли использовать параметр [out].

Рассмотрим следующий интерфейс

interface IFoo : IUnknown {
    HRESULT GetOtherFoo([out] IFoo** ppFoo);
    HRESULT Bar();
};

Какой из следующих способов вы бы порекомендовали для его использования?

<сильный>1. Проверить возвращаемое значение

CComPtr<IFoo> other;
HRESULT hr = foo->GetOtherFoo(&other);
if (SUCCEEDED(hr)) 
    other->Bar();

Это заставляет меня немного нервничать, поскольку ошибка в IFoo может вызвать разыменование указателя NULL.

<сильный>2. Проверьте выходной параметр

Это зависит от того факта, что если метод дает сбой, он не должен изменять ни один из [out] параметров (если параметр изменился ‹==> его можно безопасно использовать).

CComPtr<IFoo> other;
foo->GetOtherFoo(&other);
if (other) 
    other->Bar();

Обратите внимание, что такое происходит в любом случае, деструктор CComPtr вызовет Release, если указатель не NULL, поэтому он не может быть мусором.

<сильный>3. Параноидальный способ, проверьте оба

CComPtr<IFoo> other;
HRESULT hr = foo->GetOtherFoo(&other);
if (SUCCEEDED(hr) && other) 
    other->Bar();

На мой взгляд, это немного многословно.


P.S. См. связанный вопрос.


person Motti    schedule 04.05.2009    source источник


Ответы (2)


Если вы хотите написать больше проверок и сделать код немного медленнее, чтобы сделать его более надежным, вариант 3 для вас. Поскольку вы ожидаете, что в COM-сервере есть ошибки, вполне разумно проверить их.

person sharptooth    schedule 05.05.2009

Методы COM-сервера, которые возвращают успешный HRESULT, но устанавливают для некоторых выходных параметров значение NULL, не очень распространены. Есть несколько случаев (на ум приходит IClientSecurity::QueryBlanket), где это используется, но обычно клиент может ожидать, что все выходные параметры будут отличны от NULL, если метод вернулся успешно.

В конце концов, все дело в том, как метод документирован. Однако в случае по умолчанию я бы посчитал 1. безопасным способом.

person Johannes Passing    schedule 04.05.2009