Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Обработка непредусмотренных исключений



Функция unexpected активирует функцию, зарегистрированную вызовом set_unexpected (определяется в заголовочном файле exception). Если никакой функции не было зарегистрировано таким образом, по умолчанию вызывается terminate. Функция terminate может вызываться в следующих случаях:

1. Механизм исключений не может найти для выброшенного исключения

подходящий catch.

2. Деструктор пытается выбросить исключение в процессе разматывания

стека.

3. При попытке перебросить исключение, когда в данный момент никакое

исключение не обрабатывается.

4. Вызов функции unexpected по умолчанию вызывает terminate.

 

Посредством вызова set_ t erminate можно специфицировать функцию, активируемую при вызове terminate. В противном случае terminate будет активировать функцию abort, которая завершает программу, не вызывая никаких деструкторов еще остающихся объектов с автоматическим или статическим классом памяти. При преждевременном завершении программы это может приводить к утечкам ресурсов.

Обе функции set _ unexpected и set _ terminate возвращают указатель на последнюю функцию, вызывавшуюся соответственно функциями unexpected и terminate (или 0, если функция вызывается впервые). Это позволяет программисту сохранить указатель на функцию, чтобы впоследствии ее можно было восстановить. Функции set_unexpected и set_terminate принимают в качестве аргумента указатель на функцию без параметров с возвращаемым типом void.

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

 

Разматывание стека

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

вызывается функция terminate для завершения программы. Программа в Пример 5 демонстрирует разматывание стека.

 

Блок try в main (строки 37-41) вызывает functionl (строки 27-31). Затем functionl вызывает function2 (строки 20-24), которая в свою очередь вызывает function3 (строки 11-17). Строка 16 функции function3 выбрасывает объект runtime__error. Однако поскольку оператор throw в строке 16 не охвачен никаким try-блоком, происходит разматывание стека: выполнение function3 завершается в строке 16, и управление возвращается оператору в function2, который вызвал function3 (т.е. строке 23). Поскольку строка 23 не охвачена никаким try-блоком, снова происходит разматывание стека — function2 завершается в строке 23 и возвращает управление оператору в functionl, который вызвал function2 (т.е. строке 30). Строка 30 также не охвачена try-блоком, и стек разматывается еще раз — functionl завершается в строке 30 и возвращает управление оператору в main, вызвавшему functionl (т.е. строке 40). Этот оператор охвачен try-блоком в строках 37-41, поэтому первый подходящий catch-обработчик после этого try-блока (строки 42-46) перехватывает и обрабатывает данное исключение. В строке 44 используется функция what, чтобы вывести сообщение об ошибке. Как вы помните, это виртуальная функция класса exception, которую можно переопределить в производном классе, чтобы выводилось соответствующее сообщение.

 

Обработка отказов new с использованием функции set_new_handler

Существует дополнительное средство, которое можно применить для реализации обработки отказов new. Функция set_new_handler (с прототипом в заголовочном файле < new> ) принимает в качестве аргумента указатель на функцию, которая не принимает аргументов и возвращает void. Этот указатель регистрируется как функция, которая должна вызываться при отказах new. Тем самым программисту предоставляется стандартный метод обработки всех отказов new вне зависимости от того, в каком месте программы возникла ошибка. После того как обработчик new зарегистрирован в программе вызовом set_new_handler, операция new при отказах не будет выбрасывать 

исключений bad_alloc; вместо этого она будет пересылать ошибку зарегистрированному обработчику.

Если new удалось выделить память, она возвращает указатель на нее. Если память выделить не удается и никакой функции обработчика new с помощью set__new_handler зарегистрировано не было, операция new выбрасывает исключение bad_alloc. Если память выделить не удается и была зарегистрирована функция обработчика new, то вызывается эта функция. Стандарт C++ определяет, что функция обработчика new должна выполнить одно из следующих действий:

 

1. Увеличить объем доступной памяти путем освобождения других областей динамической памяти (либо попросить пользователя закрыть другие приложения) и возвратиться к операции new, чтобы возобновить попытки выделения памяти.

2. Выбросить исключение типа bad_alloc.

3. Вызвать функцию abort или exit (обе из заголовочного файла < cstdlib> ) для завершения программы.

 

Программа в Примере 6 демонстрирует set_new_handler. Функция customNewHandler (строки 14-18) печатает сообщение об ошибке (строка 16), а затем завершает программу вызовом abort (строка 17). Вывод показывает, что программа выполнила всего две итерации цикла, после чего new потерпела неудачу и активировала функцию customNewHandler. У вас вывод программы может отличаться от нашего в зависимости от объема физической памяти, дискового пространства, доступного для виртуальной памяти на вашей системе, и используемого компилятора.


Поделиться:



Последнее изменение этой страницы: 2019-06-08; Просмотров: 182; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.01 с.)
Главная | Случайная страница | Обратная связь