Оператор try-except

Блок, относящийся только к системам Microsoft

Оператор try-except имеет следующий синтаксис:

__try 
{
   // guarded code
}
__except ( expression )
{
   // exception handler code
}

Заметки

Оператор try-except относится к расширениям Microsoft для языков C и C++, которое позволяет целевым приложениям получать управление программой при возникновении событий, обычно завершающих выполнение программы. Такие события вызываются исключениями, а механизм, предназначенный для работы с ними, называется структурированной обработкой исключений.

Дополнительные сведения см. в разделе Оператор try-finally.

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

Примечание

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

Составной оператор после предложения __try образует тело защищенного раздела. Составной оператор после предложения __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 процесс был завершен, обработчик исключений не вызывается.

Дополнительные сведения см. в статье базы знаний Q315937 "Практическое руководство. Перехват переполнения стека в приложении Visual C++".

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

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

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

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

Механизм структурированной обработки исключений имеет две встроенных функции, которые можно использовать с оператором try-except. Это функции GetExceptionCode и GetExceptionInformation.

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

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

struct _EXCEPTION_POINTERS {
      EXCEPTION_RECORD *ExceptionRecord,
      CONTEXT *ContextRecord }

Типы указателей _EXCEPTION_RECORD и _CONTEXT определены во включаемом файле 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

Завершение блока, относящегося только к системам Microsoft

См. также

Ссылки

Написание обработчика исключений

Структурированная обработка исключений (C/C++)

Ключевые слова в C++