инструкция try-except

Инструкция try-except — это расширение, которое поддерживает структурированную обработку исключений на языках C и C++.

    // . . .
    __try {
        // guarded code
    }
    __except ( /* filter expression */ ) {
        // termination code
    }
    // . . .

грамматики

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

Замечания

Инструкция try-except — это расширение Майкрософт на языках C и C++. Он позволяет целевым приложениям управлять событиями, которые обычно завершают выполнение программы. Такие события называются структурированными исключениями или исключениями . Механизм, который касается этих исключений, называется структурированной обработкой исключений (SEH).

Дополнительные сведения см. в инструкции try-finally.

Исключения могут быть либо аппаратными, либо программными. Структурированная обработка исключений полезна, даже если приложения не могут полностью восстановиться из аппаратных или программных исключений. SEH позволяет отображать сведения об ошибках и перехватывать внутреннее состояние приложения, чтобы помочь диагностировать проблему. Это особенно полезно для периодических проблем, которые не легко воспроизвести.

Примечание.

Структурированная обработка исключений поддерживается в Win32 для исходных файлов как на C, так и на C++. Однако он не предназначен специально для C++. Для того чтобы ваш код лучше переносился, лучше использовать механизм обработки исключений языка C++. Кроме того, этот механизм отличается большей гибкостью, поскольку может обрабатывать исключения любого типа. Для программ C++ рекомендуется использовать собственную обработку исключений C++: попробуйте, перехват и вызов инструкций.

Составной оператор после __try предложения является текстом или защищенным разделом. Выражение __except также называется выражением фильтра . Его значение определяет, как обрабатывается исключение. Составной оператор после предложения __except является обработчиком исключения. Обработчик задает действия, выполняемые при возникновении исключения во время выполнения раздела текста. Выполнение происходит следующим образом:

  1. Сначала выполняется защищенный раздел.

  2. Если исключение при этом не возникает, выполнение переходит в инструкцию, стоящую после предложения __except.

  3. Если исключение возникает во время выполнения защищенного раздела или в любой подпрограмме вызовов защищенного раздела, __except выражение вычисляется. Есть три возможных значения :

    • EXCEPTION_CONTINUE_EXECUTION (-1) Исключение закрывается. Выполнение продолжается в точке, в которой возникло исключение.

    • EXCEPTION_CONTINUE_SEARCH (0) Исключение не распознано. Продолжайте поиск по стеку обработчика, сначала для содержащих try-except операторов, а затем обработчиков со следующим самым высоким приоритетом.

    • EXCEPTION_EXECUTE_HANDLER (1) Исключение распознается. Перенесите управление в обработчик исключений, выполнив __except составную инструкцию, а затем продолжайте выполнение после __except блока.

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

Каждое приложение может иметь свой собственный обработчик исключений.

Это недопустимо, чтобы перейти к оператору __try , но допустимо, чтобы выскочить из одного. Обработчик исключений не вызывается, если процесс завершается в середине выполнения try-except инструкции.

Для совместимости с предыдущими версиями _try, _except и _leave являются синонимами для __try, __exceptи __leave если параметр компилятора /Za (Отключить расширения языка) не указан.

Ключевое слово __leave.

__leave Ключевое слово действителен только в защищенном разделе try-except инструкции, и его действие заключается в переходе к концу защищенного раздела. Выполнение продолжается с первого оператора, следующего за обработчиком исключений.

Оператор goto также может выскочить из защищенного раздела, и он не снижает производительность, как это делает в инструкции try-finally . Это связано с тем, что очистка стека не происходит. Однако рекомендуется использовать __leave ключевое слово вместо инструкцииgoto. Причина заключается в том, что вы, скорее всего, сделаете ошибку программирования, если защищенный раздел большой или сложный.

Структурированные функции обработки исключений

Структурированная обработка исключений предоставляет две встроенные функции, доступные для использования с try-except инструкцией: GetExceptionCode и GetExceptionInformation.

GetExceptionCode возвращает код (32-разрядное целое число) исключения.

Встроенная функция GetExceptionInformation возвращает указатель на структуру EXCEPTION_POINTERS , содержащую дополнительные сведения об исключении. Через этот указатель можно обращаться к состоянию компьютера, которое существовало в момент возникновения аппаратного исключения. Его структура выглядит следующим образом.

typedef struct _EXCEPTION_POINTERS {
    PEXCEPTION_RECORD ExceptionRecord;
    PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

Типы PEXCEPTION_RECORD указателей и PCONTEXT определены в файле include <winnt.h> и _CONTEXT_EXCEPTION_RECORD определены в файле include <excpt.h>

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

Встроенная функция AbnormalTermination доступна в обработчике завершения. Возвращает значение 0, если текст инструкции try-finally завершается последовательно. В остальных случаях функция возвращает 1.

<Excpt.h> определяет некоторые альтернативные имена для этих встроенных элементов:

GetExceptionCode — это эквивалент _exception_code

GetExceptionInformation — это эквивалент _exception_info

AbnormalTermination — это эквивалент _abnormal_termination

Пример

// exceptions_try_except_Statement.cpp
// Example of try-except and try-finally statements
#include <stdio.h>
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>

int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
    puts("in filter.");
    if (code == EXCEPTION_ACCESS_VIOLATION)
    {
        puts("caught AV as expected.");
        return EXCEPTION_EXECUTE_HANDLER;
    }
    else
    {
        puts("didn't catch AV, unexpected.");
        return EXCEPTION_CONTINUE_SEARCH;
    };
}

int main()
{
    int* p = 0x00000000;   // pointer to NULL
    puts("hello");
    __try
    {
        puts("in try");
        __try
        {
            puts("in try");
            *p = 13;    // causes an access violation exception;
        }
        __finally
        {
            puts("in finally. termination: ");
            puts(AbnormalTermination() ? "\tabnormal" : "\tnormal");
        }
    }
    __except(filter(GetExceptionCode(), GetExceptionInformation()))
    {
        puts("in except");
    }
    puts("world");
}

Выходные данные

hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
        abnormal
in except
world

См. также

Написание обработчика исключений
Structured Exception Handling (C/C++)
Ключевые слова