Открыть сервисСервис

HRESULT

HRESULT — это 32-битный целочисленный тип данных со знаком, используемый в операционных системах семейства Microsoft Windows и в COM-технологии (Component Object Model) для возврата статуса выполнения функций и методов. В отличие от традиционного булева результата, HRESULT кодирует не только факт успеха или ошибки, но и дополнительную информацию: severity (уровень серьёзности), facility (область происхождения) и код ошибки.

Структура и формат

HRESULT представляет собой знаковое 32-битное число (тип long в C/C++). Биты распределены следующим образом:

  • Бит 31 (S) — severity (серьёзность): 0 — успех (success), 1 — неудача (failure).
  • Биты 30–28 (R, C, N) — зарезервированные биты, используемые для внутренних целей (например, для кодов, возвращаемых из пользовательских заголовков).
  • Биты 27–16 (Facility) — код области (facility), указывающий на подсистему, которая вернула результат (например, FACILITY_WIN32, FACILITY_ITF, FACILITY_RPC).
  • Биты 15–0 (Code) — непосредственно код ошибки или статуса, уникальный в пределах данной facility.

Для удобства работы в Windows SDK определены макросы: SUCCEEDED(hr) и FAILED(hr), которые проверяют только бит severity. Это означает, что значения типа S_FALSE (успех, но с отрицательным результатом) считаются успешными, хотя их числовое значение не равно нулю.

Основные значения

Существует ряд стандартных констант HRESULT, определённых в заголовочных файлах Windows:

  • S_OK (0x00000000) — операция завершилась успешно.
  • S_FALSE (0x00000001) — операция завершилась успешно, но с отрицательным результатом (например, «элемент не найден» при поиске).
  • E_FAIL (0x80004005) — неопределённая ошибка.
  • E_OUTOFMEMORY (0x8007000E) — недостаточно памяти.
  • E_INVALIDARG (0x80070057) — один из аргументов недопустим.
  • E_NOTIMPL (0x80004001) — метод не реализован.
  • E_ACCESSDENIED (0x80070005) — отказ в доступе.
  • E_POINTER (0x80004003) — недопустимый указатель.

Для преобразования системных кодов ошибок Win32 в HRESULT используется макрос HRESULT_FROM_WIN32(x). Обратное преобразование выполняется функцией HRESULT_CODE(hr).

Применение в COM и Win32

В COM каждый метод интерфейса объявляется как возвращающий HRESULT. Это позволяет единообразно обрабатывать ошибки, возникающие в разных компонентах, независимо от языка программирования. Возвращаемые данные при этом передаются через выходные параметры.

В Win32 API, начиная с ранних версий Windows, многие функции возвращают HRESULT (например, функции работы с реестром, службами, оболочкой). При этом часть функций возвращает обычный BOOL или DWORD, и для них применяются отдельные правила проверки.

Обработка ошибок

При программировании на C/C++ принято проверять результат вызова через макросы SUCCEEDED/FAILED. В языках высокого уровня (C#, Visual Basic .NET) среда автоматически преобразует HRESULT в исключения: если бит severity равен 1, генерируется исключение COMException или Marshal.ThrowExceptionForHR.

В отладочных целях строковое описание ошибки можно получить с помощью функции FormatMessage или утилиты Error Lookup Tool, входящей в состав Windows SDK.

Связанные типы

Существуют производные типы: STATUS (в ядре Windows, 32-битный, но с иной структурой битов), NTSTATUS (используется в драйверах и системных вызовах), а также DWORD для кодов ошибок Win32. Несмотря на внешнее сходство, эти типы не являются взаимозаменяемыми без явного преобразования.

Критика и особенности

Одной из проблем HRESULT является его «неочевидность» для начинающих разработчиков: значение S_FALSE часто воспринимается как ошибка, хотя формально является успехом. Кроме того, из-за того, что код ошибки занимает лишь 16 бит, в некоторых случаях возникают коллизии между ошибками из разных facility. Тем не менее, тип остаётся стандартом де-факто для всех COM- и большинства системных API Windows на протяжении более трёх десятилетий.

Источники

  • Microsoft Learn: «HRESULT (COM)» — документация по структуре и макросам.
  • Microsoft Windows SDK: заголовочные файлы winerror.h, winnt.h.
  • Книга Дона Бокса «Сущность технологии COM» (1998).
  • MSDN Magazine: статьи об обработке ошибок в COM.
Заметили ошибку или не согласны с информацией в статье? Напишите нам support@bfometr.ru