При работе программ возникают так называемые исключительные ситуации, когда дальнейшее нормальное выполнение приложения становится невозможным. Причиной исключительных ситуаций могут быть как ошибки в программе, так и неправильные действия пользователя, неверные данные и т.д.
Обычные конструкции, необходимые для проверки данных, делают более-менее серьезную программу сложночитабельной. Более того, программисту очень сложно отледить все исключительные ситуации.
Сдесь на помощь программисту приходят такие средства языка, как:
-защищенные блоки ( try -блоки) и перехваты исключений ( catch -блоки);
-инициализация исключений (инструкция throw ).
блок try-catch
Простейший формат защищенного блока имеет вид:
Важно! Многоточие является частью синтаксиса языка!
Работает эта конструкция так.
Выполняются инструкции, входящие в состав блока try (защищенный блок). Если при их выполнении исключение не возбуждается (в C++ чаще используется термин «выброс исключения»), то блок catch пропускается. При выбросе исключения выполнение защищенного блока прекращается, и начинают работать инструкции, записанные в блоке catch .
Понятие исключительной ситуации. Объекты-исключения. Оператор throw
Основной смысл этих инструкций – корректная обработка исключительной ситуации. Кроме того, в блок catch имеет смысл поместить код, который освобождает ресурсы, захваченные выполнившимися инструкциями из блока try . После окончания работы блока catch исключение считается обработанным, и управление передается на первую инструкцию, следующую за конструкцией try … catch .
Пример: перехват системного исключения «деление на ноль»
int x = 0;
try std::cout // Последующие операторы выполняться не будут
>
catch (. ) std::cout
Вот и все, и совсем не больно)
throw
Гораздо более интересным является механизм создания собственных исключений. Для их возбуждения используется оператор throw .
Тип выражения, указанного в операторе throw , определяет тип исключительной ситуации, а значение может быть передано обработчику прерываний. Этот механизм, заявленный как стандартный, представляется весьма экзотическим без использования механизма классов. И только
использование стандартных классов-исключений или разработка собственных классов
позволяют в полной мере оценить все возможности такого подхода.
Соответственно, полный формат защищенного блока имеет вид:
try
…
Первый формат используется, если нам надо указать тип перехватываемого исключения, но не нужно обрабатывать связанное с этим исключением значение (это достигается при использовании второго формата оператора catch ). Наконец, третий формат оператора catch позволяет обработать все исключения.
Обработка исключений, возбужденных оператором throw , идет по следующей схеме:
1. Создается статическая переменная со значением, заданным в операторе throw .
Она будет существовать до тех пор, пока исключение не будет обработано.
ООП — Исключительные ситуации (Exceptions) — часть 1
Если переменная-исключение является объектом класса, при ее создании работает конструктор копирования.
2. Завершается выполнение защищенного try -блока: раскручивается
стек подпрограмм,
вызываются деструкторы для тех объектов, время жизни которых истекает и т.д.
3. Выполняется поиск первого из catch -блоков, который пригоден для обработки созданного
исключения.
Поиск ведется по следующим критериям:
— если тип, указанный в catch -блоке, совпадает с типом созданного исключения,
или является ссылкой на этот тип;
— класс, заданный в catch -блоке, является предком класса, заданного в throw ,
и наследование выполнялось с ключом доступа public ;
— указатель, заданный в операторе throw , может быть преобразован по стандартным правилам к указателю, заданному в catch -блоке.
— в операторе throw задано многоточие.
Если нужный обработчик найден, то ему передается управление и, при необходимости,
значение оператора throw . Оставшиеся catch -блоки,
относящиеся к защищенному блоку, в котором было создано исключение, игнорируются.
Из указанных правил поиска следует, что очень важен порядок расположения catch -блоков.
Так, блок catch(…) должен стоять последним в списке, а блок catch (void *) – после всех блоков с указательными типами.
Если ни один из catch -блоков, указанных после защищенного блока, не сработал, то исключение считается необработанным. Его обработка может быть продолжена во внешних блоках try (если они, конечно, есть).
В конце оператора catch может стоять оператор throw без параметров. В этом случае работа catch -блока считается незавершенной а исключение – не обработанным до конца, и происходит поиск соответствующего обработчика на более высоких уровнях.
Если оператор throw был вызван вне защищенного блока (что чаще всего случается, когда исключение возбуждается в вызванной функции), или если не был найден ни один подходящий обработчик этого исключения, то вызывается стандартная функция terminate() . Она, в свою очередь, вызывает функцию abort() для завершения работы с приложением. Единственное, что доступно программисту в этом случае – зарегистрировать с помощью функции set_terminate свою функцию, которая будет выполняться перед аварийным завершением работы.
Преимущества и недостатки работы с исключениями
Возбуждение исключения не является единственным способом сообщить о возникновении
внештатной ситуации в ходе выполнения программы. Просигнализировать о возникшей ошибке
могут и другие механизмы, например:
— занесение информации о состоянии программы в специальную переменную или поле класса и использование специальных механизмов доступа к этой информации;
— задание таких спецификаций для функций, которые сигнализировали бы о наступлении
нештатной ситуации (например, использование булевских функций, которые возвращали бы
значение false при возникновении таких ситуаций);
— использование стандартных функций, сообщающих об ошибках, например perror() .
Выбор того или иного механизма реакции на нештатные ситуации достаточно сложен, поскольку
четких критериев не существует, да и не может существовать. Мы должны учитывать следующие соображения:
— игнорирование исключения приводит к аварийному завершению приложения,
а игнорирование другой информации проходит незаметно (хотя результаты могут быть и непредсказуемыми);
— если в программе есть большое число вызовов функции, которая может создать
нештатную ситуацию, то логичнее было бы включить их в один защищенный блок, нежели
выполнять проверку результатов для каждого вызова;
— с другой стороны, следует иметь в виду, что после возникновения исключительной ситуации и ее обработки работа защищенного блока не возобновляется.
Надеюсь, моя статья кому-нибудь помогла.
Источник: habr.com
Исключительные ситуации. Обработка исключительных ситуаций
Исключительные ситуации (exceptions) – события, которые происходят в процессе выполнения программы и нарушают нормальное следование потока выполнения команд. Могут возникнуть во время выполнения программы, прервав ее обычный ход. К ним относится деление на нуль, отсутствие загружаемого файла, отрицательный или вышедший за верхний предел индекс массива, переполнение выделенной памяти и др..
В объектно-ориентированных языках программирования при возникновении исключительной ситуации исполняющая система создает объект определенного класса, соответствующего возникшей ситуации, содержащий сведения о том, что, где и когда произошло. Этот объект передается на обработку программе, в которой возникло исключение. Если программа не обрабатывает исключение, то объект возвращается обработчику по умолчанию исполняющей системы. Обработчик выводит на консоль сообщение о произошедшем исключении и прекращает выполнение программы.
Блоки перехвата исключения. Для организации обработки исключения необходимо перехватить и обработать исключение в программе. Говорят, что исполняющая система или программа «выбрасывает» (throws) объект-исключение.
Этот объект «пролетает» через всю программу, появившись сначала в том методе, где произошло исключение, а программа в одном или нескольких местах пытается (try) его «перехватить» (catch) и обработать. Обработку можно сделать полностью в одном месте, а можно обработать исключение в одном месте, выбросить снова, перехватить в другом месте и обрабатывать дальше. Для того чтобы попытаться (try) перехватить (catch) объект-исключение, надо весь код программы, в котором может возникнуть исключительная ситуация, охватить оператором try<> catch о <>. Каждый блок catchou перехватывает исключение только одного типа, того, который указан в его аргументе. Но можно написать несколько блоков catch()<> для перехвата нескольких типов исключений.
Например возникают исключения двух типов. Напишем блоки их обработки:
В программу листинга вставлен блок try<> и два блока перехвата catchou для каждого типа исключений. Обработка исключения здесь заключается просто в выводе сообщения и содержимого объекта-исключения, как оно представлено методом tostring() соответствующего класса-исключения. После блоков перехвата вставлен еще один, необязательный блок finaliy().
Он предназначен для выполнения действий, которые надо выполнить обязательно, чтобы ни случилось. Все, что написано в этом блоке, будет выполнено и при возникновении исключения, и при обычном ходе программы, и даже если выход из блока try<> осуществляется оператором return. Если в операторе обработки исключений есть блок finally<>, то блок catch () <> может отсутствовать, т. е. можно не перехватывать исключение, но при его возникновении все-таки проделать какие-то обязательные действия. Кроме блоков перехвата в листинге после каждого действия делается трассировочная печать, чтобы можно было проследить за порядком выполнения программы.
Источник: studopedia.ru
Лекция 20. Исключительные ситуации
После того как вы создали и отладили (удалили ошибки) несколько программ, вы уже способны предвидеть ошибки, которые могут встретиться в программе. Например, если ваша программа читает информацию из файла, ей необходимо проверить, существует ли файл и может ли программа его открыть. Аналогично, если ваша программа использует оператор new для выделения памяти, ей необходимо проверить и отреагировать на возможное отсутствие памяти. По мере увеличения размера и сложности ваших программ вы обнаружите, что необходимо включить много таких проверок по всей программе. Из этого урока вы узнаете, как использовать исключительные ситуации C++ для упрощения проверки и обработки ошибок. К концу данного урока вы освоите следующие основные концепции:
- Исключительная ситуация (exception) представляет собой неожиданное событие — ошибку — в программе.
- В ваших программах вы определяете исключительные ситуации как классы.
- Чтобы заставить ваши программы следить за исключительными ситуациями, необходимо использовать оператор C++ try.
- Для обнаружения определенной исключительной ситуации ваши программы используют оператор C++ catch.
- Для генерации исключительной ситуации при возникновении ошибки ваши программы используют оператор C++ throw.
- Если ваша программа обнаруживает исключительную ситуацию, она вызывает специальную (характерную для данной исключительной ситуации) функцию, которая называется обработчиком исключительной ситуации.
- Некоторые (старые) компиляторы не поддерживают исключительные ситуации C++.
C++ ПРЕДСТАВЛЯЕТ ИСКЛЮЧИТЕЛЬНЫЕ СИТУАЦИИ КАК КЛАССЫ
Ваша цель при использовании исключительных ситуаций C++ состоит в упрощении обнаружения и обработки ошибок в программах. В идеале, если ваши программы обнаруживают неожиданную ошибку (исключительную ситуацию), им следует разумным образом ее обработать вместо того, чтобы просто прекратить выполнение.
В программах вы определяете каждую исключительную ситуацию как класс. Например, следующие ситуации определяют три исключительные ситуации для работы с файлами:
Позже в этом уроке вы создадите исключительные ситуации, которые используют переменные и функции-элементы класса. А пока просто поверьте, что каждая исключительная ситуация соответствует классу.
КАК ЗАСТАВИТЬ C++ ПРОВЕРЯТЬ ИСКЛЮЧИТЕЛЬНЫЕ СИТУАЦИИ
Прежде чем ваши программы могут обнаружить и отреагировать на исключительную ситуацию, вам следует использовать оператор C++ try для разрешения обнаружения исключительной ситуации. Например, следующий оператор try разрешает обнаружение исключительной ситуации для вызова функции file_соpy:
Сразу же за оператором try ваша программа должна разместить один или несколько операторов catch, чтобы определить, какая исключительная ситуация имела место (если она вообще была):
Источник: studfile.net