Стоит ли проверять наличие нулевого указателя в реализации QueryInterface()?
-
07-07-2019 - |
Вопрос
IUnknown::QueryInterface() передается параметр void **, обозначающий адрес, по которому следует поместить полученный интерфейс.
STDMETHOD QueryInterface(/* [in] */ REFIID riid, /* [iid_is][out] */ void** ppvObject)
Должна ли реализация QueryInterface() проверять этот указатель на значение null (и затем немедленно возвращать E_POINTER) или просто записывать туда?
Я видел много кода, связанного с COM, и почти везде проверка не выполняется.Гипотетически кто-то, конечно, мог бы передать нулевой указатель в качестве этого параметра, но действительно ли нужна такая проверка?
Решение
Вам (звонившему) не нужно проверять указатель на предмет отсутствия NULL
. Р>
Однако вы должны проверить возвращенный HRESULT
. Метод вернет E_POINTER
, если указатель вывода равен NULL
и E_NOINTERFACE
, если интерфейс не поддерживается.
Вызываемый должен проверить указатель на отсутствие NULL
и вернуть E_POINTER
, если это NULL
:
MSDN : возвращаемое значение:
Этот метод возвращает
S_OK
, если интерфейс поддерживается, иE_NOINTERFACE
в противном случае. ЕслиppvObject
равенNULL
, этот метод возвращаетE_POINTER
.
Другие советы
Согласно документам MSDN , QueryInterface либо возвращает S_OK, и в этом случае выходной параметр будет установлен правильно. Или он возвращает E_NOINTERFACE, в этом случае параметр out не будет установлен.
Он вернет E_POINTER, если void **, который вы передаете, равен NULL.
Я бы не стал проверять наличие нуля, скорее проверял бы возвращаемое значение из IUnknown :: QueryInterface
Вероятно, нет ничего плохого в проверке на null, но с учетом гарантий интерфейса это выглядит как избыточная проверка.
Это зависит от того, какой COM-объект вы используете (Или какое приложение размещает вас).В большинстве случаев достаточно просто проверить HRESULT.Если вы имеете дело со сторонними объектами (замена проводника и т.д.), вам, вероятно, также следует проверить наличие NULL.Explorer делает это, и поэтому вам также необходимо это сделать, если вы хотите избежать сбоев в глючных расширениях: