|
Программирование >> Разработка устойчивых систем
Библиотечная функция uncaught exception() возвращает true в процессе раскрутки стека, так что теоретически можно сравнить uncaught exception() с false и обработать возникшее исключение внутри деструктора. Тем не менее, мы еще не видели ни одной хорошей архитектуры, основанной на подобном решении, поэтому такая возможность упоминается лишь в сноске. объектов их операторы присваивания могут породить исключение, которое потребует освобождения выделенных ресурсов. Обратите внимание: в обоих обработчиках мы перезапускаем исключение. Это объясняется тем, что наши обработчики всего лишь выполняют необходимые операции по управлению ресурсами; пользователь все равно должен узнать о возникших проблемах, поэтому исключение передается дальше по динамической цепочке. Библиотеки, которые не ограничиваются молчаливым поглощением исключений, называются нейтральными по отношению к исключениям. Всегда стремитесь к тому, чтобы ваши библиотеки были как безопасными, так и нейтральными по отношению к исключениям. Внимательно просматривая ранее приведенную программу, можно заметить, что ни одна из операций delete не запускает исключения. От этого факта зависит работа программы. Вспомните: при вызове delete для объекта вызывается деструктор этого объекта. Оказывается, написать код, безопасный по отношению к исключениям, в принципе невозможно без предположения о невозможности исключений в деструкторах. Не позволяйте деструкторам запускать исключения! (Мы еще раз напомним об этом в конце главы.) Программирование с учетом исключений Для большинства программистов (а особенно программистов С) исключения являются новшеством, к которому придется привыкать. Далее приводятся рекомендации по программированию с учетом исключений. Когда лучше обойтись без исключений Исключения - не панацея; не злоупотребляйте ими. В этом разделе рассматриваются ситуации, в которых применять исключения не рекомендуется. Принимая решение об использовании исключений, лучше всего руководствоваться правилом: исключения запускаются только тогда, когда поведение функции не соответствует ее спецификации. Асинхронные события Система signal() из стандартного языка С и все аналогичные системы обрабатывают асинхронные события, то есть события, которые происходят вне нормальной последовательности выполнения программы и появление которых невозможно предугадать. Исключения С++ не могут использоваться для обработки асинхронных событий, потому что исключение и его обработчик принадлежат к одному стеку вызова. Другими словами, работа исключений основана на динамической цепочке вызовов функций в стеке программы (они имеют динамическую видимость ), тогда как асинхронные события должны обрабатываться совершенно отдельным кодом (как правило - процедурами обработки прерываний или циклами событий), который не входит в нормальную последовательность выполнения программы. Не запускайте исхшючения из обработчиков прерываний! Программирование с учетом исключений 55 Впрочем, это не значит, что асинхронные события не могут ассоциироваться с исключениями. Просто обработчик прерывания должен отработать как можно быстрее и вернуть управление. Обычно для этого в обработчике прерывания устанавливается флаг, синхронно проверяемый в основном коде программы. Устранимые ошибки Если вы располагаете достаточной информацией для обработки ошибки, запускать исключение не требуется. Решите проблему в текущем контексте, не передавая ее в контекст более высокого уровня. Кроме того, исключения С++ не запускаются для событий машинного уровня (таких, как деление на ноль). Предполагается, что такие события обрабатываются другими средствами, например операционной системой или оборудованием. При таком подходе ис1слючения С++ работают с разумной эффективностью, а их применение ограничивается условиями программного уровня. Управление последовательностью выполнения На первый взгляд кажется, что исключения представляют собой альтернативный механизм возврата управления или отдаленное подобие команды switch. У некоторых программистов возникает искушение использовать ис1слючения вместо стандартных языковых механизмов, но делать этого не стоит. Прежде всего, обработка исключений значительно уступает по эффективности нормальному выполнению программы. Не стоит идти на затраты, связанные с исключениями, в обычной программе. Кроме того, исключения, причиной которых не являются ошибки, собьют с толку пользователей вашего класса или функции. Исключения не обязательны Некоторые программы (например, несложные утилиты, ограничивающиеся получением ввода и его элементарной обработкой) достаточно просты. В таких программах тоже могут происходить сбои: неудачные попытки выделения памяти, открытия файлов и т. д. В таких программах можно вывести сообщение и поручить системе прибрать за программой , вместо того чтобы самостоятельно перехватывать все исключения и освобождать все ресурсы. Короче говоря, если ваша программа может обойтись без исключений - не используйте их. Новые исключения, старый код Еще одна характерная ситуация возникает при модификации существующих программ, не поддерживающих исключения. Допустим, к системе подключается библиотека, в которой используются исключения; нужно ли изменять весь существующий код? Если в системе уже имеется нормальная схема обработки ошибок, самое тривиальное решение - заключить максимально большой блок, в котором используется новая библиотека (возможно, это будет весь код main()), в блок try с catch(...) с выводом простейших сообщений об ошибках. Представленная схема может уточняться до произвольной степени за счет добавления специализированных обработчиков, но в любом случае объем нового кода должен быть минимальным. Еще лучше изолировать код, генерирующий исключения, в блоке try, и написать обработчики для перевода исключений в существующую схему обработки ошибок. Некоторые компиляторы генерируют исключения в подобных случаях, но обычно у них предусмотрен специальный ключ для подавления этого (нестандартного) поведения. Очень важно помнить об исключениях при создании библиотеки, которой будут пользоваться другие - особенно если вы не знаете, как им потребуется реагировать на критические ошибки (вспомните, что уже говорилось о безопасности исключений и о том, почему в стандартной библиотеке С++ отсутствуют спецификации исключений). Типичные применения исключений Используйте исхслючения для решения следующих задач: проблемы с повторным вызовом функции, в которой произошло исключение; восстановление и продолжение программы без повторного вызова функции; выполнение всех возможных действий в текущем контексте и перезапуск того же исключения в контексте следующего уровня; выполнение всех возможных действий в текущем контексте и запуск другого исключения в контекст следующего уровня; завершение программы; создание оболочек для функций (особенно библиотечных функций С), использующих обычные схемы обработки ошибок; упрощение программы. Громоздкие и неудобные системы обработки ошибок нередко усложняют работу программ. Возможно, исключения упростят обработку ошибок и повысят ее эффективность; повышение надежности библиотеки и программы. Выигрыш достигается как краткосрочный (отладка), так и долгосрочный (повышение устойчивости приложения). Когда использовать спецификации исключений Спецификация исштючений похожа на прототип функции: она указывает пользователю, что он должен написать код обработки ошибок, и сообщает, какие исключения нужно обрабатывать. По спецификации компилятор узнает, какие ис1слючения могут быть сгенерированы функцией, чтобы обнаружить возможные нарушения на стадии выполнения. Простой просмотр кода не всегда позволяет определить, какие исключения могут быть запущены той или иной функцией. Иногда вызываемая функция порождает непредвиденные исключения, а иногда старая функция, не запускавшая исключений, заменяется новой функцией с исключениями, что приводит к вызову unexpected(). Каждый раз, когда вы используете спецификации исключений или вызываете функции, в которых они есть, подумайте о создании собственной функции unexpectedO. Такая функция регистрирует сообщение, а затем либо запускает исключение, либо завершает программу. Как объяснялось ранее, не стоит использовать спецификации исключений в шаблонных классах, поскольку у вас нет информации о том, какие типы исключений могут запускаться классами-параметрами.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |