Structured Exception Handling (C/C++)

Структурированная обработка исключений (SEH) — это расширение Майкрософт для C и C++ для обработки определенных исключительных ситуаций кода, таких как ошибки оборудования, корректно. Хотя Windows и Microsoft C++ поддерживают SEH, рекомендуется использовать обработку исключений C++ стандарта ISO в коде C++. Это делает код более переносимым и гибким. Однако для поддержания существующего кода или для определенных типов программ может потребоваться использовать SEH.

Только для систем Майкрософт:

грамматики

try-except-statement :
__try compound-statement __except ( filter-expression ) compound-statement

try-finally-statement :
__try compound-statement __finally compound-statement

Замечания

С помощью SEH можно убедиться, что ресурсы, такие как блоки памяти и файлы, будут освобождены правильно, если выполнение неожиданно завершается. Вы также можете справиться с конкретными проблемами ( например, недостаточной памяти), используя краткий структурированный код, который не зависит от goto инструкций или сложного тестирования кодов возврата.

Инструкции try-except , try-finally упомянутые в этой статье, являются расширениями Майкрософт на языках C и C++. Они поддерживают SEH, позволяя приложениям получать контроль над программой после событий, которые в иных ситуациях привели бы к завершению выполнения. Хотя обработка ошибок SEH работает с исходными файлами C++, она не была создана специально для этого языка. Если вы используете SEH в программе C++, которая компилируется с помощью /EHa или /EHsc параметром, деструкторы для локальных объектов вызываются, но другое поведение выполнения может не быть ожидаемым. Пример см. далее в этой статье. В большинстве случаев вместо SEH рекомендуется использовать обработку исключений C++ стандарта ISO. С помощью обработки исключений C++ можно повысить переносимость кода и обрабатывать исключения любого типа.

Если у вас есть код C, использующий SEH, можно смешать его с кодом C++, использующим обработку исключений C++. Дополнительные сведения см. в разделе "Обработка структурированных исключений" в C++.

Существует два механизма SEH.

Эти два типа обработчиков отличаются, но тесно связаны с процессом, известным как очистка стека. При возникновении структурированного исключения Windows ищет последний установленный обработчик исключений, который сейчас активен. Обработчик может выполнить одно из трех действий:

  • Не удается распознать исключение и передать управление другим обработчикам (EXCEPTION_CONTINUE_SEARCH).

  • Распознать исключение, но закрыть его (EXCEPTION_CONTINUE_EXECUTION).

  • Распознайте исключение и обработайте его (EXCEPTION_EXECUTE_HANDLER).

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

По мере развертывания стека операционная система вызывает все обработчики завершения, которые были написаны для каждой функции. Используя обработчик завершения, вы очищаете ресурсы, которые в противном случае останутся открытыми из-за ненормального завершения. Если вы ввели критически важный раздел, его можно выйти из обработчика завершения. Когда программа завершит работу, вы можете выполнять другие задачи по обслуживанию дома, такие как закрытие и удаление временных файлов.

Следующие шаги

Пример

Как упоминалось ранее, деструкторы для локальных объектов вызываются, если вы используете SEH в программе C++ и компилируете его с помощью /EHa или /EHsc параметра. Однако поведение во время выполнения может не быть ожидаемым, если вы также используете исключения C++. В этом примере показаны эти различия в поведении.

#include <stdio.h>
#include <Windows.h>
#include <exception>

class TestClass
{
public:
    ~TestClass()
    {
        printf("Destroying TestClass!\n");
    }
};

__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
    printf("Throwing C++ exception\n");
    throw std::exception("");
#else
    printf("Triggering SEH exception\n");
    volatile int *pInt = 0x00000000;
    *pInt = 20;
#endif
}

__declspec(noinline) void TestExceptions()
{
    TestClass d;
    TestCPPEX();
}

int main()
{
    __try
    {
        TestExceptions();
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        printf("Executing SEH __except block\n");
    }

    return 0;
}

Если вы используете /EHsc для компиляции этого кода, но макрос CPPEX локального элемента управления тестом не определен, TestClass деструктор не выполняется. Выходные данные выглядят следующим образом:

Triggering SEH exception
Executing SEH __except block

Если вы используете /EHsc для компиляции кода и CPPEX определяется с помощью /DCPPEX (поэтому создается исключение C++), TestClass выполняется деструктор и выходные данные выглядят следующим образом:

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

Если вы используете /EHa для компиляции кода, TestClass деструктор выполняет выполнение исключения с помощью стандартного выражения C++ throw или SEH. То есть определяется ли CPPEX он. Выходные данные выглядят следующим образом:

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

Дополнительные сведения см. в разделе /EH (Модель обработки исключений)

КОНЕЦ Только для систем Майкрософт

См. также

Обработка исключений
Ключевые слова
<exception>
Ошибки и обработка исключений
Структурированная обработка исключений (Windows)