- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Основы объектно-ориентированного программирования - Бертран Мейер
Шрифт:
Интервал:
Закладка:
Первым контрпримером механизма (наиболее полно представленным в Unix, но доступным и на других платформах, реализующих C) является процедура signal, вызываемая в следующей форме:
signal (signal_code, your_routine)
с эффектом вызова обработчика исключения - программы your_routine, когда выполнение текущей программы прерывается, выдавая соответствующий код сигнала (signal_code). Код сигнала - целочисленная константа, например, SIGILL (неверная инструкция - illegal instruction) или SIGFPE (переполнение с плавающей точкой - floating-point exception). В программу можно включить сколь угодно много вызовов процедуры signal, что позволяет обрабатывать различные, возможные ошибки.
Теперь предположим, что при выполнении некоторой инструкции произошло прерывание и выработан соответствующий код сигнала. Будет или нет вызвана процедура signal, но выполнение программы завершается в не нормальном состоянии. Предположим, что вызывается обработчик события - your_routine, пытающийся исправить ситуацию. Беда в том, что, завершив работу, он возвращает управление непосредственно в точку, где произошло прерывание (в не нормальное состояние). Это опасно, вероятнее всего, из этой точки невозможно нормально продолжить работу.
Что необходимо в большинстве подобных случаев - исправить ситуацию и продолжить выполнение, начиная с некоторой особой точки, но не точки прерывания. Мы увидим, что есть простой механизм, реализующий эту схему. Заметьте, он может быть реализован и на C, на большинстве платформ. Достаточно комбинировать процедуру signal с двумя другими библиотечными процедурами: setjmp, вставляющую маркер в точку, допускающую продолжение вычислений, и longjmp для возврата к маркеру. С механизмом setjmp-longjmp следует обращаться весьма аккуратно. Поэтому он не ориентирован на обычных программистов, но может использоваться разработчиками компиляторов для реализации высокоуровневого механизма ОО-исключений, который будет описан в этой лекции.
Как не следует делать это - Ada пример
Приведу пример программы, взятый из одного учебника12.1) по языку Ada.
sqrt (x: REAL) return REAL is
begin
if x < 0.0 then
raise Negative
else
normal_square_root_computation
end
exception
when Negative =>
put ("Negative argument")
return
when others => ...
end -- sqrt
Этот пример, вероятно, предназначался для синтаксической иллюстрации механизма Ada, и был написан быстро (он, например, отказывается возвращать значение в случае возникновения исключения). Поэтому было бы непорядочно критиковать его, как если бы это был настоящий пример хорошего программирования. Вместе с тем, он ясно показывает нежелательный способ обработки исключений. Поскольку Ada ориентирована на военные и космические приложения, то остается надеяться, что ни одна из реальных программ не следует буквально этой модели.
Целью программы является получение вещественного квадратного корня из вещественного числа. Но что если число отрицательно? В языке Ada нет утверждений, так что в программе проводится проверка, возбуждающая исключение для отрицательных чисел.
Инструкция raise Exc прерывает выполнение текущей программы и включает исключение с кодом Exc. Это исключение может быть захвачено и обработано при наличии предложений exception, имеющих вид:
exception
when code_a1, code_a2, ...=> Instructions_a;
when code_b1, ... => Instructions_b;
...
Если код исключения совпадает с одним из кодов, указанных в части when, то выполняются соответствующие инструкции. Если, как в примере, есть предложение when others, то его инструкции выполняются, когда код исключения не совпадает ни с одним из кодов предыдущих частей when. Если нет универсального обработчика when others, и код исключения не совпадает ни с одним кодом, то поиск обработчика будет вестись у вызывающей программы, если вызывающей программы нет, то достигнута программа main и программа завершается отказом.
В примере нет необходимости переходить к вызывающей программе, поскольку выброшенное исключение с кодом Negative захватывается обработчиком с таким же кодом.
Но что делают соответствующие инструкции? Посмотрите еще раз:
put ("Negative argument")
return
Напечатается сообщение - довольно глубокомысленное, а затем управление перейдет к вызывающей программе, которая, не будучи уведомлена о событии, продолжит свое выполнение, как если бы ничего не случилось. Вспоминая снова о типичных приложениях Ada, можно лишь надеяться, что этой схеме не следует артиллерийское приложение, в результате которой снаряды могут упасть на головы совсем не тех солдат, для которых вряд ли может служить утешением посланное сообщение об ошибке.
Эта техника, вероятно, хуже, чем C-Unix сигнальный механизм, позволяющий, по крайней мере, возобновить вычисление в точке, где оно остановилось. Обработчик исключения when, заканчивающийся инструкцией return, даже не продолжает текущую программу; он возвращает управление вызывающей программе, будто бы все прекрасно, в то время как все далеко не прекрасно.
Этот контрпример дает хороший урок Ada-программистам: почти ни при каких обстоятельствах обработчик when не должен заканчиваться return. Слово "почти" употреблено для полноты картины, поскольку есть особый допустимый случай ложной тревоги (false alarm), достаточно редкий, который мы обсудим чуть позже. Опасно и неприемлемо не уведомлять вызывающую программу о возникшей ошибке. Если невозможно исправить ситуацию и выполнить контракт, то программа должна выработать отказ. Язык Ada позволяет сделать это: предложение exception может заканчиваться инструкцией raise без параметров, повторно выбрасывая исходное исключение, передавая его вызывающей программе. Это и есть подходящий способ завершения выполнения, когда невозможно выполнить свой контракт.
Правило исключений языка Ada
Выполнение любого обработчика исключений должно заканчиваться либо выполнением инструкции raise, либо повторением объемлющего программного блока.
Принципы обработки исключений
Контрпримеры помогли указать дорогу к дисциплинированному использованию исключений. Следующие принципы послужат основой обсуждения.
Принципы дисциплинированной обработки исключений
Есть только два легитимных отклика на исключение, возникшее при выполнении программы:
1 Повторение (Retrying) - попытка изменить условия, приведшие к исключению, и выполнить программу повторно, начиная все сначала.
2 Отказ (Failure) - известный также как "организованная паника" (organized panic): чистка стека и других ресурсов, завершение вызова и отчет об отказе перед вызывающей программой.
В дополнение, некоторые сигналы операционной системы (случай (3) в классификации исключений) в редких случаях являются откликом на "ложную тревогу". Определив, что исключение безвредно, можно возобновить выполнение в точке прерывания.
Давайте начнем рассмотрение с третьего случая - ложной тревоги, обработка которого соответствует основному механизму C-Unix. Вот пример. Некоторые оконные системы будут вызывать исключения, если пользователь перестраивает размеры окна во время выполнения процесса в этом окне. Предположим, что процесс не выполняет никакого вывода в это окно, тогда исключение будет безвредным, и можно возобновить выполнение процесса в прерванной точке. Но даже в этом случае есть лучшие пути, такие как полная блокировка сигналов на время выполнения процесса, чтобы исключение вообще не встретилось. Именно так мы будем поступать с ложными тревогами в механизме, рассматриваемом в следующем разделе.
Ложные тревоги возможны лишь для одного вида сигналов операционной системы - благоприятных сигналов, но нельзя игнорировать арифметическое переполнение или невозможность выделения запрашиваемой памяти. Исключения всех других категорий также указывают на трудности, не допускающие игнорирования. Было бы абсурдно, например, запускать программу при ложном предусловии.
Повторение - более обнадеживающая стратегия: мы потерпели поражение в битве, но не проиграли войну. Хотя наш первоначальный план выполнения контракта потерпел неудачу, мы можем постараться удовлетворить клиента, применив другую тактику. Если она будет успешной, то исключение не оказывает никакого влияния на клиента. После одной или нескольких попыток, приведших к неудаче, в очередной попытке нам, возможно, удастся полностью выполнить контракт ("Миссия завершена, сэр. Обычные, небольшие проблемы, сэр. Теперь все хорошо, сэр").
