|
Программирование >> Полиморфизм без виртуальных функций в с++
авторы библиотек и другие программисты станут просто возбуждать исключения, не пытаясь понять, в чем проблема и как устранить ее. Время покажет, в какой мере оправдалось пророчество Дуга. Естественно, что никакое языковое средство не может запретить программисту писать плохие програ.ммы. Первые реализации обработки исключений в том виде, который описан в ARM, начали появляться весной 1992 г. 16.2. Цели и предположения При проектировании были сделаны предположения о то.м, что: □ исключения используются преимущественно для обработки ошибок; □ обработчики исключений встречаются реже, чем определения функций; □ по сравнению с вызовами функций исключения возникают редко; □ исключения - это понятие уровня языка, а не компилятора, и не стратегия обработки ошибок в узком смысле. Данные фор.мулировки, равно как и изложенный ниже перечень желаемых возможностей, взяты со слайдов, на которых демонстрировалась эволюция проектирования с 1988 г. Обработка исключений: □ задумывалась не как простая альтернатива .механизму возврата - так предлагали некоторые, в особенности Дэвид Черитон (David Cheriton), - а как специальный механизм для поддержки построения отказоустойчивых систем; □ предназначается не для того, чтобы превратить каждую функцию в отказоустойчивую единицу. Задумана как механизм, с помощью которого подсистема может выдерживать отказы даже тогда, когда составляющие ее функции написаны без соблюдения единой стратегии обработки ошибок; □ не должна навязывать проектировщику одно единственное правильное представление о том, как следует обрабатывать ошибки. Цель обработки исключений - сделать язык более выразительным. На протяжении всей работы по проектированию возрастало влияние проектировщиков разнообразных систем и уменьшалось число предложений от сообщества пользователей языка. За прошедшее с тех пор время наибольшее воздействие на проектирование обработки исключений в С-ы- оказала работа по отказоустойчивым системам, начатая в университете Ньюкасла в Англии Брайаном Рэпделло.м и его коллега.ми и продолженная в других местах. В процессе проектирования обработки исключений были выработаны приведенные ниже критерии. 1. Передача произвольного объема информации из точки, где возбуждено исключение, обработчику с сохранением данных о типе. 2. Отсутствие дополнительных издержек по скорости и по памяти в коде, не возбуждающем исключения. 3. Гарантии того, что любое возбужденное исключение будет перехвачено каким-то обработчиком. Цели и предположения j 389 4. Возможность группировать исключения так, чтобы можно было написать обработчик, перехватывающий не только одно, но и сразу несколько исключений. 5. Механизм, который по умолчанию будет правильно работать в .миогопоточ-ной среде. 6. Механизм, допускающий взаимодействие с другими языками и особенно с С. 7. Простота использования. 8. Простота реализации. Большая часть этих критериев была воплощена в жизнь, но третий и вось.мой принципы всегда оказывались либо требующими больпп1Х затрат, либо слишком ограничительны.ми, поэтому в результате мы лишь приблизились к их реализацин. Я считаю это неплохим результатом, принимая во внимание то, что обработка исключений - трудная задача, для решения которой программисту понадобится вся помощь, которую только можно получить. Чрез.мерно ревностный проектировщик языка мог бы включить средства или ограничения, которые лишь усложнили бы проектирование и реализацию отказоустойчивой систе.мы. Думается, что отказоустойчивая систе.ма должна быть многоуровневой. Отдельная часть системы не может восстановиться после любого .мыслимого сбоя и некорректных воздействий извне. Возможны ведь и крайние случаи: отказ питания или непроизвольное изменение содержимого ячейки памяти. В какой-то момент отдельный модуль системы может отказать, и тогда ситуация будет решаться на более высоком уровне этой системы. Например, вызванная функция может сообщить о катастрофической ошибке вызывающей; процесс может завершиться аномально и порзить другому процессу разобраться с последствиями; процессор может обратиться за помощью к другому процессору. Компьютер может затребовать помощь у оператора-человека. Подчеркнем в связи с этим: обработку ошибок следует проектировать так, чтобы у относительно простой профаммы, пользующейся сравнительно несложны.ми средствами обработки исключений, был шанс выполнить свою задачу. Попытка дать такие средства, которые позволили бы одной монолитной программе восстановиться после любых ошибок, - неверный шаг, который ведет к стратегия.м обработки настолько сложным, что они сами становятся источпико.м ошибок. 16.3. Синтаксис Как обычно, синтаксису было уделено достаточное внимание, и в результате я остановился на не слишком лаконичном варианте, в котором было три ключевых слова и обилие скобок: int f() { try { начало try-блока return g(); catch (xxii) { начало обработчика исключения int g() { ... if (что то случилось) throw xxiiO; возбудить исключение Ключевое слово try, очевидно, избыточно, равно как и скобки {}, если только try-блок или обработчик не состоят из нескольких предложений. Например, совсем несложно было бы разрешить такой синтаксис: int f() { return g() catch (xxii) { не С++ error( ошибка в g(): xxii ); return 22; Однако его так трудно объяснить, что я решил пойти на избыточность, дабы избавить персонал службы технической поддержки от вопросов запутавшихся пользователей. Из-за традиционной нелюбви пользователей С к новым ключевым словам я всячески пытался уйти от этого, но все схемы, которые приходили на ум, оказывались слишком хитроумными или сбивающими с толку. Так, я пробовал использовать одно слово catch и для возбуждения и для перехвата исключения. Это можно было бы сделать логически непротиворечиво, но объяснить такую схему я бы не взялся. Слово throw было выбрано отчасти из-за того, что более очевидные слова raise и signal уже были заняты под функции из стандартной библиотеки С. 16.4. Группировка Поговорив с десятком пользователей десятка разных систем, поддерживающих в том или ином виде обработку исключений, я пришел к выводу, что необходимо уметь группировать исключения. Например, пользователь должен иметь возможность перехватить любое исключение библиотеки ввода/вывода, даже не зная точно, какими они бывают. Есть, конечно, и обходные пути в ситуации, когда механизм группировки отсутствует. Например, тип исключения можно закодировать в виде данных, передаваемых вместе с единственным исключением. Допустимо просто перечислять исключения, логически входящие в одну группу, всякий раз, когда нужно обработать их все. Однако любая такая уловка расценивалась бы если и не всеми, то большинством людей как осложняющая сопровождения. Мы с Эндрю Кенигом попробовали было схему, основанную на том, что группы создавались динамически с помощью конструкторов для объектов исключений. сюда попадаем только тогда, когда случилось xxii error( ошибка в g(): xxii ); return 22;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |