Оператор 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 является обработчиком исключения. Он задает набор действий, выполняемых при возникновении исключения в теле защищенного раздела. Выполнение происходит следующим образом:
Сначала выполняется защищенный раздел.
Если исключение при этом не возникает, выполнение переходит в инструкцию, стоящую после предложения __except.
Если же исключение возникло (при выполнении защищенного раздела или любой вызванной из него процедуры), то вычисляется выражение __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
См. также
Ссылки
Написание обработчика исключений