Из Википедии, свободной энциклопедии
Перейти к навигацииПерейти к поиску

В вычислительной и компьютерное программирование , обработка исключений является процесс реагирования на возникновение исключений - аномальных или исключительных условий , требующих специальной обработки - во время исполнения в виде программы . Как правило, исключение прерывает нормальный поток выполнения и запускает предварительно зарегистрированный обработчик исключений ; детали того, как это делается, зависят от того, является ли это исключение аппаратного или программного обеспечения и как реализовано исключение программного обеспечения. Обработка исключений, если таковая предусмотрена, облегчается специализированным языком программирования.конструкции, аппаратные механизмы, такие как прерывания , или средства межпроцессного взаимодействия (IPC) операционной системы (ОС), такие как сигналы . Некоторые исключения, особенно аппаратные, могут обрабатываться настолько изящно, что выполнение может возобновиться с того места, где оно было прервано.

Альтернативный подход к обработке в программном обеспечении за исключение является проверкой ошибок , [1] , который поддерживает нормальный ход выполнения программы с более поздней явными проверками на непредвиденные обстоятельства , сообщили об использовании специальных возвращаемых значений, вспомогательных глобальных переменном , таких как C ' s егты или плавающей точка флагов состояния. Проверка ввода , которая упреждающе фильтрует исключительные случаи, также является подходом.

На оборудовании

Механизмы аппаратных исключений обрабатываются ЦП. Он предназначен для поддержки, например, обнаружения ошибок и перенаправляет поток программы на служебные процедуры обработки ошибок. Состояние до исключения сохраняется, например, в стеке. [2]

Аппаратная обработка исключений / ловушки: IEEE 754 с плавающей запятой

Обработка исключений в аппаратном стандарте IEEE 754 с плавающей запятой в целом относится к исключительным условиям и определяет исключение как «событие, которое происходит, когда операция с некоторыми конкретными операндами не имеет результата, подходящего для каждого разумного приложения. Эта операция может сигнализировать об одном или нескольких исключениях. вызывая стандартную или, если явно запрошенную, альтернативную обработку, определяемую языком ".

По умолчанию исключение IEEE 754 является возобновляемым и обрабатывается путем замены предопределенного значения для различных исключений, например бесконечность для исключения деления на ноль, и предоставления флагов состояния для последующей проверки того, произошло ли исключение (см. Язык программирования C99 для типичного пример обработки исключений IEEE 754). Стиль обработки исключений, обеспечиваемый использованием флагов состояния, включает: сначала вычисление выражения с использованием быстрой и прямой реализации; проверка наличия сбоя путем тестирования флагов состояния; а затем, при необходимости, вызов более медленной, более устойчивой в числовом отношении реализации. [3]

Стандарт IEEE 754 использует термин «перехват» для обозначения вызова предоставляемой пользователем подпрограммы обработки исключений в исключительных условиях и является дополнительной функцией стандарта. Стандарт рекомендует несколько сценариев использования для этого, включая реализацию предварительной подстановки значения не по умолчанию с последующим возобновлением для краткой обработки устраняемых особенностей . [3] [4] [5]

Поведение по умолчанию при обработке исключений IEEE 754 при возобновлении после предварительной подстановки значения по умолчанию позволяет избежать рисков, присущих изменению потока управления программой для числовых исключений. Например, в 1996 году первый полет Ariane 5 (рейс 501) закончился катастрофическим взрывом, отчасти из-за политики обработки исключений языка программирования Ada , заключающейся в прерывании вычислений при арифметической ошибке, которая в данном случае была 64-битной плавающей точкой. в 16-битное целочисленное преобразование переполнение . [4]В случае с Ariane Flight 501 программисты защитили только четыре из семи критических переменных от переполнения из-за проблем с вычислительными ограничениями бортового компьютера и полагались на то, что оказалось неверными предположениями о возможном диапазоне значений для три незащищенные переменные, потому что они повторно использовали код из Ariane 4, для которого их предположения были правильными. [6] По словам Уильяма Кахана , потери рейса 501 можно было бы избежать, если бы использовалась политика обработки исключений IEEE 754 с заменой по умолчанию, потому что переполнение 64-битного преобразования в 16-битное, которое привело к прерыванию работы программного обеспечения, произошло в фрагмент кода, который оказался совершенно ненужным на Ariane 5. [4]В официальном отчете о катастрофе (подготовленном комиссией по расследованию во главе с Жаком-Луи Лионсом ) отмечалось, что «основной темой в разработке Ariane 5 является уклон в сторону уменьшения случайного отказа . Поставщик инерциальной навигационной системы(SRI) только следовал данной спецификации, которая предусматривала, что в случае любого обнаруженного исключения процессор должен быть остановлен. Произошедшее исключение произошло не из-за случайного отказа, а из-за ошибки конструкции. Исключение было обнаружено, но было неправильно обработано, поскольку было принято мнение, что программное обеспечение следует считать правильным, пока не будет обнаружена его ошибка. [...] Хотя сбой произошел из-за систематической ошибки проектирования программного обеспечения, могут быть введены механизмы для смягчения этого типа проблемы. Например, компьютеры в SRI могли бы продолжать предоставлять свои наилучшие оценки требуемого отношенияИнформация. Есть основания опасаться, что программная исключительная ситуация должна быть разрешена или даже обязательна, чтобы вызвать остановку процессора при работе с критически важным оборудованием. Действительно, потеря правильной функции программного обеспечения опасна, потому что одно и то же программное обеспечение работает в обоих модулях SRI. В случае Ariane 501 это привело к отключению двух все еще исправных критически важных единиц оборудования » [7].

С точки зрения обработки аппаратные прерывания аналогичны возобновляемым исключениям, хотя обычно они не связаны с потоком управления пользовательской программы .

Средства обработки исключений, предоставляемые операционной системой

Unix-подобные операционные системы предоставляют средства для обработки исключений в программах через IPC . Как правило, прерывания, вызванные выполнением процесса, обрабатываются подпрограммами обслуживания прерываний операционной системы, и операционная система может затем отправить сигнал этому процессу, который, возможно, попросил операционную систему зарегистрировать обработчик сигнала для вызова. при возникновении сигнала или позволить операционной системе выполнить действие по умолчанию (например, завершить программу). Типичными примерами являются SIGSEGV , SIGBUS , SIGILL и SIGFPE .

Другие операционные системы, например OS / 360 и последующие , могут использовать другие подходы вместо или в дополнение к IPC.

В программном обеспечении

Обработка программных исключений и поддержка, предоставляемая программными инструментами, несколько отличается от того, что понимается под обработкой исключений на оборудовании, но используются аналогичные концепции. В механизмах языка программирования для обработки исключений термин исключение обычно используется в определенном смысле для обозначения структуры данных, хранящей информацию об исключительном условии. Одним из механизмов передачи управления, или поднять исключение, известен как бросок . Считается, что исключение выброшено . Исполнение переведено на «уловку».

С точки зрения автора подпрограммы , создание исключения - полезный способ сообщить, что подпрограмма не может нормально выполняться - например, когда входной аргумент недопустим (например, значение находится за пределами домена функции ) или когда ресурс, на который она опирается, недоступен (например, отсутствующий файл, ошибка жесткого диска или ошибки нехватки памяти), или если процедура обнаружила нормальное состояние, требующее особой обработки, например, внимание, конец файла . В системах без исключений подпрограммы должны возвращать некоторый специальный код ошибки . Однако это иногда осложняется проблемой полупредиката , когда пользователям подпрограммы необходимо писать дополнительный код, чтобы отличать нормальные возвращаемые значения от ошибочных.

Языки программирования существенно различаются по своим представлениям о том, что такое исключение. Современные языки можно условно разделить на две группы: [8]

  • К этой категории относятся языки, на которых исключения предназначены для использования в качестве структур управления потоком: Ada, Modula-3, ML, OCaml, PL / I, Python и Ruby.
  • Языки, в которых исключения используются только для обработки ненормальных, непредсказуемых, ошибочных ситуаций: C ++, [9] Java, [10] C #, Common Lisp, Eiffel и Modula-2.

Кинири также отмечает, что «дизайн языка лишь частично влияет на использование исключений и, следовательно, на способ обработки частичных и полных сбоев во время выполнения системы. книги, журнальные статьи и дискуссионные форумы в Интернете, а также стандарты кодекса организации ". [8]

Современные приложения сталкиваются с множеством проблем проектирования при рассмотрении стратегий обработки исключений. В частности, в современных приложениях уровня предприятия исключения часто должны пересекать границы процессов и машин. Частью разработки надежной стратегии обработки исключений является распознавание того момента, когда процесс вышел из строя до такой степени, что он не может быть экономически обработан программной частью процесса. [11]

История

Программная обработка исключений, разработанная в Лиспе в 1960-х и 1970-х годах. Это произошло в LISP 1.5 (1962), где исключения были пойманной по ERRSETключевому слову, который вернулся NILв случае ошибки, вместо завершения программы или ввода отладчика. [12] Повышение ошибок было введено в MacLisp в конце 1960-х с помощью ERRключевого слова. [12] Это было быстро использовано не только для повышения ошибок, но и для нелокального потока управления, и поэтому было дополнено двумя новыми ключевыми словами, CATCHи THROW(MacLisp, июнь 1972 г.), резервирование ERRSETиERRдля обработки ошибок. Поведение при очистке, которое сейчас обычно называется "finally", было введено в NIL (новая реализация LISP) в середине-конце 1970-х годов как UNWIND-PROTECT. [13] Затем он был принят Common Lisp . Современным с этим было dynamic-windв Scheme, который обрабатывал исключения при закрытии. Первыми работами по структурированной обработке исключений были Гуденаф (1975a) и Гуденаф (1975b) . [14] Обработка исключений впоследствии стала широко применяться во многих языках программирования, начиная с 1980-х годов.

PL / I использовал исключения с динамической областью видимости, однако в более поздних языках используются исключения с лексической областью видимости. Обработка исключений PL / I включала события, которые не являются ошибками, например внимание, конец файла, изменение перечисленных переменных. Хотя некоторые более свежие языки поддерживают исключения, не связанные с ошибками, их использование не является обычным явлением. [ необходима цитата ]

Первоначально обработка программных исключений включала как возобновляемые исключения (семантика возобновления), как и большинство аппаратных исключений, так и невозобновляемые исключения (семантика завершения). Однако семантика возобновления считалась неэффективной на практике в 1970-х и 1980-х годах (см. Обсуждение стандартизации C ++, цитируемое ниже) [15] и больше не используется широко, хотя и обеспечивается такими языками программирования, как Common Lisp, Dylan и PL / I.

Семантика завершения

Механизмы обработки исключений в современных языках обычно не возобновляются («семантика завершения»), в отличие от аппаратных исключений, которые обычно возобновляются. Это основано на опыте использования того и другого, поскольку существуют теоретические аргументы и аргументы в пользу любого решения; они широко обсуждались в ходе дискуссий о стандартизации C ++ в 1989–1991 годах, в результате чего было принято окончательное решение о семантике завершения. [15] По поводу обоснования такой конструкции механизма C ++ Страуструп отмечает:

[На] встрече в Пало-Альто [стандартизация C ++] в ноябре 1991 года мы услышали блестящее резюме аргументов в пользу семантики завершения, подкрепленное как личным опытом, так и данными от Джима Митчелла (из Sun, ранее из Xerox PARC). Джим использовал обработку исключений на полдюжине языков в течение 20 лет и был одним из первых сторонников возобновления семантики в качестве одного из основных разработчиков и разработчиков системы Xerox Cedar / Mesa . Его сообщение было

«Прекращение предпочтительнее возобновления; это не вопрос мнения, а вопрос многолетнего опыта. Возобновление соблазнительно, но недействительно ».

Он подкрепил это заявление опытом работы с несколькими операционными системами. Ключевым примером был Cedar / Mesa: он был написан людьми, которые любили и использовали возобновление, но после десяти лет использования в системе в полмиллиона строк осталось только одно использование возобновления - и это был контекстный запрос. Поскольку на самом деле возобновление не было необходимым для такого запроса контекста, они удалили его и обнаружили значительное увеличение скорости в этой части системы. В каждом случае, когда использовалось возобновление, оно - за десять лет - становилось проблемой, и его заменял более подходящий дизайн. По сути, каждое использование возобновления означало неспособность сохранять отдельные уровни абстракции несвязанными. [14]

Критика

Противоположный взгляд на безопасность обработки исключений был дан Тони Хоаром в 1980 году, описав язык программирования Ada как имеющий «... множество функций и условных обозначений, многие из которых являются ненужными, а некоторые из них, например обработка исключений, даже опасно. [...] Не позволяйте использовать этот язык в его нынешнем состоянии в приложениях, где надежность критична [...]. Следующая ракета, которая сбится с пути из-за ошибки языка программирования, может быть не исследовательской космическая ракета в безобидном путешествии к Венере: это может быть ядерная боеголовка, взорвавшаяся над одним из наших городов ». [16]

Обработка исключений часто неправильно обрабатывается в программном обеспечении, особенно при наличии нескольких источников исключений; Анализ потока данных 5 миллионов строк кода Java обнаружил более 1300 дефектов обработки исключений. [17] Ссылаясь на многочисленные предыдущие исследования других авторов (1999–2004 гг.) И их собственные результаты, Веймер и Некула писали, что серьезная проблема с исключениями состоит в том, что они «создают скрытые пути потока управления, о которых программистам трудно рассуждать». [17] : 8:27

Изначально Go был выпущен без явной обработки исключений, а разработчики утверждали, что он запутывает поток управления . [18] Позже в язык был добавлен механизм исключения panic/ recover, который авторы Go советуют использовать только для неисправимых ошибок, которые должны остановить весь процесс. [19] [20] [21] [22]

Исключения, такие как неструктурированный поток, увеличивают риск утечки ресурсов (например , выход из раздела, заблокированного мьютексом , или раздела , временно удерживающего открытый файл) или несогласованного состояния. Существуют различные методы управления ресурсами при наличии исключений, чаще всего комбинирующие шаблон удаления с некоторой формой защиты от откручивания (например, finallyпредложение), которая автоматически освобождает ресурс, когда элемент управления выходит из раздела кода.

Поддержка исключений в языках программирования

Многие компьютерные языки имеют встроенную поддержку исключений и обработки исключений. Сюда входят ActionScript , Ada , BlitzMax , C ++ , C # , Clojure , COBOL , D , ECMAScript , Eiffel , Java , ML , оболочка следующего поколения , Object Pascal (например, Delphi , Free Pascal и т.п.), PowerBuilder , Objective-C , OCaml , PHP (начиная с версии 5),PL / I , PL / SQL , Prolog , Python , REALbasic , Ruby , Scala , Seed7 , Smalltalk , Tcl , Visual Prolog и большинство языков .NET . Обработка исключений на этих языках обычно не возобновляется, и когда возникает исключение, программа выполняет обратный поиск по стеку вызовов функций, пока не будет найден обработчик исключения.

Некоторые языки требуют раскрутки стека по мере продвижения этого поиска. То есть, если функция f , содержащая обработчик H для исключения E , вызывает функцию g , которая, в свою очередь, вызывает функцию h , и исключение E возникает в h , тогда функции h и g могут быть завершены, и H в f будет обрабатывать E .

Языками обработки исключений без этой раскрутки являются Common Lisp с его системой условий , PL / I и Smalltalk . Все вызывают обработчик исключений и не раскручивают стек; однако в PL / I, если "ON unit" (обработчик исключений) выполняет GOTO из ON, это раскручивает стек. Обработчик исключений имеет возможность перезапустить вычисление, возобновить или прекратить выполнение. Это позволяет программе продолжить вычисления в том же месте, где произошла ошибка (например, когда ранее отсутствующий файл стал доступен), или реализовать уведомления, ведение журнала, запросы и переменные жидкости поверх механизма обработки исключений (как сделано в Smalltalk). Бесстековая реализация Mythryl язык программирования поддерживает постоянную обработку исключений без раскручивания стека.

За исключением незначительных синтаксических различий, используется всего несколько стилей обработки исключений. В наиболее популярном стиле исключение инициируется специальным оператором ( throwили raise) с объектом исключения (например, с Java или Object Pascal) или значением специального расширяемого перечислимого типа (например, с Ada или SML). Возможности для обработчиков исключений начинаются с маркерами пунктом ( tryили блок - стартером языка , такие как begin) и заканчивается в начале первого пункта обработчика ( catch, except, rescue). За этим может следовать несколько предложений обработчика, и в каждом можно указать, какие типы исключений он обрабатывает и какое имя использует для объекта исключения.

Некоторые языки также допускают предложение ( else), которое используется в случае, если исключение не произошло до того, как будет достигнут конец области действия обработчика.

Более распространенным является связанное предложение ( finallyили ensure), которое выполняется независимо от того, произошло исключение или нет, обычно для высвобождения ресурсов, полученных в теле блока обработки исключений. Примечательно, что C ++ не предоставляет эту конструкцию, поскольку он поддерживает технику Resource Acquisition Is Initialization (RAII), которая освобождает ресурсы с помощью деструкторов .

В целом код обработки исключений может выглядеть так (в Java- подобном псевдокоде ):

попробуйте  {  line  =  console . readLine (); if  ( line . length ()  ==  0 )  {  throw  new  EmptyLineException ( «Строка, прочитанная с консоли, была пустой!» );  } консоль . printLine ( "Привет,% s!"  %  строка );  консоль . printLine ( "Программа успешно выполнилась ." ); } catch  ( EmptyLineException  e )  {  консоль . printLine ( «Привет!» ); } catch  ( исключение  e )  {  console . printLine ( "Ошибка:"  +  е . сообщение ()); } наконец  {  console .printLine ( "Программа завершается." ); }

В качестве незначительного изменения некоторые языки используют единственное предложение обработчика, которое имеет дело с классом исключения внутренне.

Согласно статье 2008 года Уэстли Веймера и Джорджа Некулы , синтаксис блоков try... finallyв Java является фактором, способствующим дефектам программного обеспечения. Когда метод должен обрабатывать получение и высвобождение 3-5 ресурсов, программисты, очевидно, не хотят вкладывать достаточно блоков из-за проблем с удобочитаемостью, даже если это было бы правильным решением. Можно использовать один блок try... finallyдаже при работе с несколькими ресурсами, но это требует правильного использования контрольных значений , что является еще одним распространенным источником ошибок для этого типа проблем. [17] : 8: 6–8: 7 Относительно семантики try... catch...finallyВ целом, Веймер и Некула пишут, что «Хотя try-catch-finally концептуально прост, он имеет наиболее сложное описание выполнения в спецификации языка [Gosling et al. 1996] и требует четырех уровней вложенных« if »в своем официальное описание на английском языке. Короче говоря, оно содержит большое количество угловых случаев, которые программисты часто упускают из виду ». [17] : 8: 13–8: 14

C поддерживает различные средства проверки ошибок, но , как правило, не считается для поддержки «обработки исключений,» хотя эти setjmpи longjmpстандартные библиотечные функции могут быть использованы для реализации исключений семантики.

Perl имеет дополнительную поддержку для структурированной обработки исключений.

Поддержка обработки исключений в Python является повсеместной и последовательной. Трудно написать эффективную программу Python без использования его tryи exceptключевых слов. [ необходима цитата ]

Обработка исключений в иерархиях пользовательского интерфейса

Последние интерфейсные веб-фреймворки, такие как React и Vue , представили механизмы обработки ошибок, при которых ошибки распространяются вверх по иерархии компонентов пользовательского интерфейса аналогично тому, как ошибки распространяются вверх по стеку вызовов при выполнении кода. [23] [24] Здесь механизм границы ошибки служит аналогом типичного механизма try-catch. Таким образом, компонент может гарантировать, что ошибки от его дочерних компонентов будут обнаружены и обработаны, а не распространены на родительские компоненты.

Например, во Vue компонент будет отлавливать ошибки, реализуя errorCaptured

Vue . component ( 'parent' ,  {  template :  '<div> <slot> </slot> </div>' ,  errorCaptured :  ( err ,  vm ,  info )  =>  alert ( 'Произошла ошибка' ); }) Vue . компонент ( 'дочерний' ,  {  шаблон :  '<div> {{cause_error ()}} </div>' })

При таком использовании в разметке:

< родитель >  < ребенок > </ ребенок > </ родитель >

Ошибка, вызванная дочерним компонентом, перехватывается и обрабатывается родительским компонентом. [25]

Реализация обработки исключений

Реализация обработки исключений в языках программирования обычно требует значительной поддержки как со стороны генератора кода, так и со стороны исполняющей системы, сопровождающей компилятор. (Именно добавление обработки исключений в C ++ завершило полезный срок службы исходного компилятора C ++, Cfront . [26] ) Наиболее распространены две схемы. Первая, динамическая регистрация , генерирует код, который постоянно обновляет структуры о состоянии программы с точки зрения обработки исключений. [27] Как правило, это добавляет новый элемент в макет кадра стека.который знает, какие обработчики доступны для функции или метода, связанных с этим фреймом; если возникает исключение, указатель в макете направляет среду выполнения на соответствующий код обработчика. Этот подход компактен с точки зрения места, но увеличивает накладные расходы на выполнение при входе и выходе из кадра. Он обычно использовался во многих реализациях Ada, например, где сложная поддержка генерации и времени выполнения уже требовалась для многих других языковых функций. Динамическая регистрация довольно проста для определения, но поддается проверке правильности . [28]

Вторая схема, реализованная во многих компиляторах C ++ производственного качества, основана на табличном подходе. Это создает статические таблицы на время компиляции и время связи , которые относятся диапазоны программного счетчика в состоянии программы по обработке исключений. [29] Затем, если генерируется исключение, система времени выполнения ищет текущее местоположение инструкции в таблицах и определяет, какие обработчики задействованы и что необходимо сделать. Такой подход сводит к минимуму административные издержки в случае, когда исключение не генерируется. Это происходит за счет некоторого пространства, но это пространство может быть выделено под специальные разделы данных, предназначенные только для чтения, которые не загружаются или не перемещаются до тех пор, пока на самом деле не будет сгенерировано исключение. [30] Этот второй подход также является лучшим с точки зрения обеспечения безопасности потоков [ необходима цитата ] .

Также были предложены другие схемы определения и реализации. [31] Для языков, поддерживающих метапрограммирование , были продвинуты подходы, которые вообще не связаны с накладными расходами (помимо уже существующей поддержки отражения ). [32]

Обработка исключений на основе дизайна по контракту

Другой взгляд на исключения основан на принципах контрактного проектирования и поддерживается, в частности, языком Eiffel . Идея состоит в том, чтобы обеспечить более строгую основу для обработки исключений, точно определив, что является «нормальным» и «ненормальным» поведением. В частности, подход основан на двух концепциях:

  • Неудача : неспособность операции выполнить свой контракт. Например, сложение может вызвать арифметическое переполнение (оно не выполняет контракт на вычисление хорошего приближения к математической сумме); или процедура может не соответствовать своему постусловию.
  • Исключение : ненормальное событие, происходящее во время выполнения подпрограммы (эта подпрограмма является « получателем » исключения) во время ее выполнения. Такое ненормальное событие возникает из-за сбоя операции, вызванной подпрограммой.

«Принцип безопасной обработки исключений», представленный Бертраном Мейером в книге «Объектно-ориентированное программное обеспечение», затем утверждает, что существует только два значимых способа реагирования подпрограммы при возникновении исключения:

  • Отказ или «организованная паника»: процедура исправляет состояние объекта путем восстановления инварианта (это «организованная» часть), а затем дает сбой (паника), вызывая исключение в вызывающей стороне (так что ненормальное событие не игнорируется).
  • Повторить: процедура снова пробует алгоритм, обычно после изменения некоторых значений, так что у следующей попытки будет больше шансов на успех.

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

Вот пример, выраженный в синтаксисе Eiffel. Предполагается, что процедура send_fastобычно является лучшим способом отправки сообщения, но может дать сбой, вызвав исключение; в таком случае алгоритм будет использовать следующий send_slow, что будет реже давать сбой. В случае send_slowсбоя процедура sendв целом должна завершиться ошибкой, в результате чего вызывающая сторона получит исключение.

send  ( m :  MESSAGE )  is  - Отправить m через быструю ссылку, если возможно, в противном случае через медленную ссылку. local  try_fast ,  try_slow :  BOOLEAN делать,  если  try_fast,  затем  try_slow  : =  True  send_slow  ( m )  else  try_fast  : =  True  send_fast  ( m )  end rescue,  если  не  try_slow,  затем  повторять  конец end

Логические локальные переменные инициализируются значением False в начале. В случае send_fastнеудачи тело ( doпредложение) будет выполнено снова, вызывая выполнение send_slow. Если это выполнение send_slowзавершается неудачно, rescueпредложение будет выполняться до конца с no retry(без elseпредложения в финале if), что приведет к сбою выполнения подпрограммы в целом.

Этот подход имеет то достоинство, что четко определяет, что такое «нормальный» и «ненормальный» случаи: ненормальный случай, вызывающий исключение, - это тот случай, когда процедура не может выполнить свой контракт. Он определяет четкое распределение ролей: doпредложение (нормальное тело) отвечает за достижение или попытку достижения контракта рутины; rescueпункт отвечает за восстановление контекста и перезапуска процесса, если это имеет шанс на успех, но не выполнять какие - либо фактические вычисления.

Хотя исключения в Eiffel имеют довольно ясную философию, Кинири (2006) критикует их реализацию, потому что «Исключения, которые являются частью определения языка, представлены значениями INTEGER, а определяемые разработчиком исключения - значениями STRING. [...] Кроме того, потому что они являются базовыми значениями, а не объектами, они не имеют внутренней семантики, кроме той, которая выражена во вспомогательной подпрограмме, которая обязательно не может быть надежной из-за действующей перегрузки представления (например, нельзя различать два целых числа с одним и тем же значением) ». [8]

Неперехваченные исключения

Если исключение выброшено, но не перехвачено (с точки зрения работы, исключение выбрасывается, когда не указан применимый обработчик), неперехваченное исключение обрабатывается средой выполнения; процедура, которая делает это, называетсяобработчик неперехваченных исключений . [33] [34] Наиболее распространенным поведением по умолчанию является завершение программы и вывод на консоль сообщения об ошибке, обычно включающего отладочную информацию, такую ​​как строковое представление исключения итрассировку стека. [33] [35] [36] Этого часто можно избежать, используя обработчик верхнего уровня (уровня приложения) (например, вцикле событий), который перехватывает исключения до того, как они достигнут среды выполнения. [33] [37]

Обратите внимание, что даже несмотря на то, что неперехваченное исключение может привести к аварийному завершению программы (программа может быть некорректной, если исключение не обнаружено, в частности, из-за того, что не откатываются частично завершенные транзакции или не высвобождаются ресурсы), процесс завершается нормально (при условии, что среда выполнения работает правильно), поскольку среда выполнения (которая контролирует выполнение программы) может обеспечить упорядоченное завершение процесса.

В многопоточной программе неперехваченное исключение в потоке может вместо этого привести к завершению только этого потока, а не всего процесса (неперехваченные исключения в обработчике уровня потока перехватываются обработчиком верхнего уровня). Это особенно важно для серверов, где, например, сервлет (работающий в собственном потоке) может быть завершен без воздействия на сервер в целом.

Этот обработчик неперехваченных исключений по умолчанию может быть переопределен либо глобально, либо для каждого потока, например, для обеспечения альтернативного ведения журнала или отчетов конечного пользователя о неперехваченных исключениях или для перезапуска потоков, которые завершаются из-за неперехваченного исключения. Например, в Java это делается для одного потока через Thread.setUncaughtExceptionHandlerи глобально через Thread.setDefaultUncaughtExceptionHandler; в Python это делается путем модификации sys.excepthook.

Статическая проверка исключений

Проверенные исключения

Разработчики Java разработали [38] проверенные исключения [39], которые представляют собой особый набор исключений. Проверенные исключения, которые может вызвать метод, являются частью сигнатуры метода . Например, если метод может генерировать объект IOException, он должен явно объявить этот факт в своей сигнатуре метода. В противном случае возникает ошибка времени компиляции.

Кинири (2006) отмечает, однако, что библиотеки Java (как они были в 2006 году) часто были непоследовательными в своем подходе к сообщению об ошибках, потому что «не все ошибочные ситуации в Java представлены исключениями. Многие методы возвращают специальные значения, которые указывают на ошибку, закодированную как постоянное поле связанных классов ". [8]

Проверенные исключения связаны со средствами проверки исключений, которые существуют для языка программирования OCaml . [40] Внешний инструмент для OCaml является невидимым (т. Е. Не требует каких-либо синтаксических аннотаций) и необязательным (т. Е. Можно скомпилировать и запустить программу без проверки исключений, хотя это не рекомендуется для производственного кода).

У языка программирования CLU была особенность с интерфейсом, более близким к тому, что Java представила позже. Функция может вызывать только исключения, перечисленные в ее типе, но любые утечки исключений из вызываемых функций будут автоматически превращаться в единственное исключение времени выполнения failure, вместо того, чтобы приводить к ошибке времени компиляции. Позже Модула-3 имела похожую особенность. [41] Эти функции не включают проверку времени компиляции, которая является центральной в концепции проверенных исключений, и не были (по состоянию на 2006 г.) включены в основные языки программирования, кроме Java. [42]

Ранние версии языка программирования C ++ включали дополнительный механизм для проверенных исключений, называемый спецификациями исключений . По умолчанию любая функция может генерировать любое исключение, но это может быть ограничено throwпредложением, добавленным к сигнатуре функции, в котором указывается, какие исключения может вызывать функция. Спецификации исключений не применялись во время компиляции. Нарушения привели к вызову глобальной функции . [43]std::unexpected Может быть дана пустая спецификация исключения, что означает, что функция не вызовет исключения. Это не было сделано по умолчанию, когда в язык была добавлена ​​обработка исключений, потому что это потребовало бы слишком большой модификации существующего кода, затруднило бы взаимодействие с кодом, написанным на других языках, и могло бы соблазнить программистов написать слишком много обработчиков на локальном уровне. уровень. [43] Явное использование пустых спецификаций исключений может, однако, позволить компиляторам C ++ выполнять значительную оптимизацию кода и разметки стека, что исключается, когда обработка исключений может происходить в функции. [30] Некоторые аналитики считали труднодостижимым правильное использование спецификаций исключений в C ++. [44]Такое использование спецификаций исключений было включено в C ++ 03 , объявлено устаревшим в стандарте языка C ++ 2012 ( C ++ 11 ), [45] и удалено из языка в C ++ 17 . Функция, которая не будет генерировать никаких исключений, теперь может быть обозначена noexceptключевым словом.

В отличие от Java, такие языки, как C #, не требуют объявления какого-либо типа исключения. Согласно Ханспетеру Мёссенбёку, отсутствие различия между вызываемыми (проверяемыми) исключениями и исключениями, которые не следует вызывать (непроверенными), делает написанную программу более удобной, но менее надежной, поскольку неперехваченное исключение приводит к прерыванию с ошибкой. трассировка стека . [46] Кинири (2006), однако, отмечает, что Java JDK (версия 1.4.1) выдает большое количество непроверенных исключений: одно на каждые 140 строк кода, тогда как Эйфель использует их гораздо реже, с одним выбросом на 4600 строк кода. . Кинири также пишет: «Как известно любому программисту Java, объемtry catchкод в типичном приложении Java иногда больше, чем сопоставимый код, необходимый для явной проверки формальных параметров и возвращаемого значения на других языках, в которых нет проверенных исключений. Фактически, общее мнение среди опытных программистов на Java состоит в том, что работа с проверенными исключениями почти такая же неприятная задача, как и написание документации. Таким образом, многие программисты сообщают, что они «недовольны» проверенными исключениями. Это приводит к обилию проверенных, но игнорируемых исключений ». [8] Кинири также отмечает, что разработчики C #, очевидно, находились под влиянием такого рода пользовательского опыта, и им приписывается следующая цитата (через Эрика Ганнерсона):

«Изучение небольших программ приводит к выводу, что требование спецификаций исключений может как повысить продуктивность разработчиков, так и повысить качество кода, но опыт работы с крупными программными проектами предполагает другой результат - снижение производительности и незначительное повышение качества кода или его отсутствие». [8]

По словам Андерса Хейлсберга, в их проектной группе было довольно широкое согласие не проверять исключения в качестве языковой функции в C #. Хейлсберг объяснил в интервью, что

«Предложение throws, по крайней мере, так, как оно реализовано в Java, не обязательно заставляет вас обрабатывать исключения, но если вы не обрабатываете их, оно заставляет вас точно подтверждать, какие исключения могут пройти. Это требует, чтобы вы либо перехватывали объявленные исключения, либо помещали их в свой собственный пункт throws. Чтобы обойти это требование, люди делают нелепые вещи. Например, они украшают каждый метод «выдает исключение». Это полностью лишает возможности эту функцию, и вы просто заставляете программиста писать еще больше свалившейся ерунды. Это никому не помогает ». [47]

Взгляды на использование

Проверенные исключения могут во время компиляции снизить частоту появления необработанных исключений во время выполнения в данном приложении. Непроверенные исключения (такие как объекты JavaRuntimeException и Error) остаются необработанными.

Однако для проверенных исключений могут потребоваться подробные throwsобъявления, раскрывающие детали реализации и уменьшающие инкапсуляцию , или поощрять кодирование плохо продуманных блоков, которые могут скрывать допустимые исключения от соответствующих обработчиков. [ необходима цитата ] Примите во внимание растущую базу кода с течением времени. Интерфейс может быть объявлен так, чтобы генерировать исключения X и Y. В более поздней версии кода, если кто-то хочет генерировать исключение Z, это сделает новый код несовместимым с предыдущими использованиями. Кроме того, с шаблоном адаптераtry/catch, в котором одно тело кода объявляет интерфейс, который затем реализуется другим телом кода, так что код может быть подключен и вызван первым, код адаптера может иметь богатый набор исключений для описания проблем, но принудительно использовать типы исключений, объявленные в интерфейсе.

Можно уменьшить количество объявленных исключений либо путем объявления суперкласса всех потенциально генерируемых исключений, либо путем определения и объявления типов исключений, подходящих для уровня абстракции вызываемого метода [48], и сопоставления им исключений более низкого уровня. типы, желательно обернутые с использованием цепочки исключений , чтобы сохранить основную причину. Кроме того, вполне возможно, что в приведенном выше примере с изменяющимся интерфейсом вызывающий код также должен быть изменен, поскольку в некотором смысле исключения, которые может генерировать метод, в любом случае являются частью неявного интерфейса метода.

Использование объявления или обычно достаточно для выполнения проверки в Java. Хотя это может иметь некоторую пользу, по сути, это обходит механизм проверенных исключений, который Oracle не одобряет. [49]throws Exceptioncatch (Exception e)

Непроверенные типы исключений обычно не должны обрабатываться, за исключением, возможно, крайних уровней области видимости. Они часто представляют собой сценарии, которые не позволяют восстановление: RuntimeExceptions часто отражают программные дефекты [50] и Errors обычно представляют собой неисправимые сбои JVM. Даже на языке, который поддерживает проверенные исключения, бывают случаи, когда использование проверенных исключений неуместно. [51]

Динамическая проверка исключений

Смысл процедур обработки исключений - гарантировать, что код может обрабатывать условия ошибки. Чтобы установить, что процедуры обработки исключений являются достаточно надежными, необходимо представить код с широким спектром недопустимых или неожиданных входных данных, например, которые могут быть созданы с помощью внедрения ошибок программного обеспечения и тестирования мутаций (что также иногда называют нечетким тестирование ). Одним из наиболее сложных типов программного обеспечения, для которого можно написать процедуры обработки исключений, является программное обеспечение протокола, поскольку надежная реализация протокола должна быть подготовлена ​​для приема входных данных, которые не соответствуют соответствующей спецификации (-ям).

Чтобы гарантировать, что значимый регрессионный анализ может проводиться на протяжении всего процесса жизненного цикла разработки программного обеспечения , любое тестирование обработки исключений должно быть в высокой степени автоматизировано, а тестовые примеры должны создаваться в научном, воспроизводимом виде. Существует несколько коммерчески доступных систем, которые выполняют такое тестирование.

В средах среды выполнения, таких как Java или .NET , существуют инструменты, которые подключаются к механизму выполнения, и каждый раз, когда возникает интересующее исключение, они записывают отладочную информацию, которая существовала в памяти на момент создания исключения ( стек вызовов и куча значения). Эти инструменты называются инструментами автоматической обработки исключений или перехвата ошибок и предоставляют информацию об основных причинах исключений.

Синхронность исключений

В некоторой степени с концепцией проверенных исключений связана синхронность исключений . Синхронные исключения происходят в конкретном программном операторе, тогда как асинхронные исключения могут возникать практически где угодно. [52] [53] Отсюда следует, что асинхронная обработка исключений не может требоваться компилятором. С ними также сложно программировать. Примеры естественно асинхронных событий включают нажатие Ctrl-C для прерывания программы и получение такого сигнала , как «стоп» или «приостановка», от другого потока выполнения .

Языки программирования обычно решают эту проблему, ограничивая асинхронность, например, Java не рекомендует использовать исключение ThreadDeath, которое использовалось для того, чтобы один поток мог останавливать другой. [54] Вместо этого могут быть полуасинхронные исключения, которые возникают только в подходящих местах программы или синхронно.

Системы кондиционирования

Common Lisp , Dylan и Smalltalk имеют систему условий [55] (см. Common Lisp Condition System ), которая охватывает вышеупомянутые системы обработки исключений. В этих языках или средах появление условия («обобщение ошибки» согласно Кенту Питману ) подразумевает вызов функции, и только в конце обработчика исключения может быть принято решение развернуть стек.

Условия - это обобщение исключений. Когда возникает условие, ищется и выбирается соответствующий обработчик условия в порядке стека для обработки условия. Условия, которые не представляют собой ошибки, могут безопасно остаться без обработки; их единственная цель может заключаться в распространении подсказок или предупреждений пользователю. [56]

Постоянные исключения

Это связано с так называемой моделью возобновления обработки исключений, в которой некоторые исключения считаются продолжаемыми : разрешается вернуться к выражению, сигнализирующему об исключении, после выполнения корректирующих действий в обработчике. Система условий обобщается таким образом: внутри обработчика несерьезного состояния (также известного как продолжаемое исключение ) можно перейти к предопределенным точкам перезапуска (также известным как перезапуски ), которые лежат между сигнальным выражением и обработчиком условия. Перезапуски - это функции, закрытые в некоторой лексической среде, позволяющие программисту восстановить эту среду перед полным выходом из обработчика условий или даже частичным разворачиванием стека.

Примером является условие ENDPAGE в PL / I; блок ON может записать строки завершения страницы и строки заголовка для следующей страницы, а затем пропустить, чтобы возобновить выполнение прерванного кода.

Перезапускает отдельный механизм от политики

Кроме того, обработка условий обеспечивает отделение механизма от политики . Перезапуски предоставляют различные возможные механизмы восстановления после ошибки, но не выбирают, какой механизм подходит в данной ситуации. Это область обработчика условий, который (поскольку он находится в коде более высокого уровня) имеет доступ к более широкому представлению.

Пример: предположим, что существует библиотечная функция, цель которой - анализировать единственную запись в файле системного журнала . Что должна делать эта функция, если запись неверна? Нет однозначного правильного ответа, потому что одну и ту же библиотеку можно использовать в программах для самых разных целей. В интерактивном браузере файлов журнала правильным решением может быть возвращение записи без анализа, чтобы пользователь мог ее видеть, но в программе автоматического суммирования журналов правильным решением может быть предоставление нулевых значений для нечитаемые поля, но прерываются с ошибкой, если слишком много записей было искажено.

Другими словами, на этот вопрос можно ответить только с точки зрения более широких целей программы, которые неизвестны универсальной библиотечной функции. Тем не менее, выход с сообщением об ошибке лишь в редких случаях является правильным ответом. Таким образом, вместо того, чтобы просто выйти с ошибкой, функция может установить перезапуски, предлагая различные способы продолжения - например, пропустить запись в журнале, предоставить значения по умолчанию или нулевые значения для нечитаемых полей, запросить у пользователя отсутствующие значения или чтобы раскрутить стек и прервать обработку с сообщением об ошибке. Предлагаемые перезапуски представляют собой доступные механизмы восстановления после ошибки; выбор перезапуска обработчиком условий обеспечивает политику .

См. Также

  • Синтаксис обработки исключений
  • Автоматическая обработка исключений
  • Исключительная безопасность
  • Продолжение
  • Защитное программирование
  • setjmp / longjmp
  • Тройная ошибка
  • Векторная обработка исключений (VEH)
  • Типы опционов и типы результатов , альтернативные способы обработки ошибок в функциональном программировании без исключений
  • Ловушка (вычисления)

Ссылки

  1. ^ «Руководство по исправлению ошибки« Исключение системного потока не обработано »» . whatt.org . Архивировано из оригинального 25 сентября 2016 года . Проверено 8 января 2019 .
  2. ^ «Обнаружение аппаратных исключений» . ИНСТРУМЕНТЫ ТЕХАСА. 2011-11-24. Архивировано из оригинала на 2013-11-10 . Проверено 5 октября 2012 .
  3. ^ а б Сяое Ли ; Джеймс Деммел (1994). «Более быстрые численные алгоритмы за счет обработки исключений, транзакции IEEE на компьютерах, 43 (8)»: 983–992. Цитировать журнал требует |journal=( помощь )
  4. ^ a b c В. Кахан (5 июля 2005 г.). «Демонстрация предварительной замены для ∞ / ∞» (PDF) . Архивировано 10 марта 2012 года (PDF) .
  5. ^ Джон Хаузер (1996). «Обработка исключений с плавающей запятой в числовых программах, транзакции ACM на языках программирования и системах 18 (2)»: 139–174. Цитировать журнал требует |journal=( помощь )
  6. ^ "Уроки Арианы" . www.irisa.fr . Архивировано 4 июня 2016 года . Проверено 5 мая 2018 .
  7. ^ «АРИАНА 5 Отказ - Полный отчет» . Архивировано 26 апреля 2014 года . Проверено 16 июля 2014 .
  8. ^ Б с д е е Kiniry, JR (2006). «Исключения в Java и Eiffel: две крайности в разработке и применении исключений». Расширенные темы в методах обработки исключений . Конспект лекций по информатике. 4119 . С. 288–300. DOI : 10.1007 / 11818502_16 . ISBN 978-3-540-37443-5.
  9. ^ "Страуструп: FAQ по стилю и технике C ++" . www.stroustrup.com . Архивировано 2 февраля 2018 года . Проверено 5 мая 2018 .
  10. ^ Блох, Джошуа (2008). «Правило 57: Используйте исключения только в исключительных ситуациях» . Эффективная Java (второе издание) . Эддисон-Уэсли. п. 241 . ISBN 978-0-321-35668-0.
  11. ^ Все исключения обрабатываются, Джим Уилкокс, «Все исключения обрабатываются» . Архивировано 18 марта 2015 года . Проверено 8 декабря 2014 .
  12. ^ a b Gabriel & Steele 2008 , стр. 3.
  13. Перейти ↑ White 1979 , p. 194.
  14. ^ a b Страуструп 1994 , стр. 392.
  15. ^ a b Страуструп 1994 , 16.6 Обработка исключений: возобновление против прекращения, стр. 390–393.
  16. CAR Hoare. «Старая одежда императора». Лекция по Премии Тьюринга 1980 года
  17. ^ а б в г Веймер, Вт; Некула, GC (2008). «Исключительные ситуации и надежность программ» (PDF) . Транзакции ACM по языкам и системам программирования . 30 (2). Архивировано (PDF) из оригинала 23 сентября 2015 года.
  18. ^ «Часто задаваемые вопросы» . Архивировано 03 мая 2017 года . Проверено 27 апреля 2017 . Мы считаем, что привязка исключений к структуре управления, как в идиоме try-catch-finally, приводит к запутанному коду. Это также побуждает программистов отмечать слишком много обычных ошибок, таких как невозможность открытия файла, как исключительные.
  19. ^ Паники и восстановить в архив 2013-10-24 в Вайбак Machine , Go вики
  20. ^ «Еженедельная история снимков» . golang.org . Архивировано 3 апреля 2017 года.
  21. ^ "Предложение для механизма, подобного исключениям" . голанг-орехи . 25 марта 2010 . Проверено 25 марта 2010 года .
  22. ^ "Эффективный ход" . golang.org . Архивировано 06 января 2015 года.
  23. ^ «Границы ошибок» . Реагировать . Проверено 10 декабря 2018 .
  24. ^ "Vue.js API" . Vue.js . Проверено 10 декабря 2018 .
  25. ^ «Обработка ошибок с Vue.js» . CatchJS . Проверено 10 декабря 2018 .
  26. ^ Скотт Мейерс , Самое важное программное обеспечение C ++ ... Архивировано 28 апреля 2011 г.на Wayback Machine , 2006 г.
  27. ^ Д. Кэмерон, П. Фауст, Д. Ленков, М. Мехта, "Переносимая реализация обработки исключений C ++", Труды конференции C ++ (август 1992 г.) USENIX .
  28. ^ Грэм Хаттон, Джоэл Райт, « Компиляция исключений, правильно заархивированных 11 сентября2014 г. на Wayback Machine ». Материалы 7-й Международной конференции по математике построения программ , 2004.
  29. ^ Lajoie, Josée (март-апрель 1994). «Обработка исключений - Поддержка механизма выполнения». Отчет C ++ . 6 (3).
  30. ^ a b Шиллинг, Джонатан Л. (август 1998 г.). «Оптимизация обработки исключений C ++». Уведомления SIGPLAN . 33 (8): 40–47. DOI : 10.1145 / 286385.286390 . S2CID 1522664 . 
  31. ^ " " Архивная копия " . Архивировано из оригинала 01.01.2012 . Проверено 27.02.2012 .CS1 maint: archived copy as title (link)", Корпорация Intel .
  32. ^ М. Hof, Х. Mössenböck, П. Pirkelbauer, " нулевая Накладные Обработка исключения с помощью Метапрограммирования в архиве 2016-03-03 в Wayback Machine ", Труды SOFSEM'97 , ноябрь 1997, Lecture Notes в области компьютерных науках 1338 , стр. 423-431.
  33. ^ a b c Библиотека разработчика Mac , « Неперехваченные исключения, заархивированные 4 марта 2016 г. на Wayback Machine »
  34. ^ MSDN , Событие AppDomain.UnhandledException, заархивировано 4 марта 2016 г. на Wayback Machine
  35. ^ Учебное пособие по Python , « 8. Ошибки и исключения, заархивированные 01.09.2015 на Wayback Machine »
  36. ^ «Практики Java -> Обеспечьте обработчик неперехваченных исключений» . www.javapractices.com . Архивировано 9 сентября 2016 года . Проверено 5 мая 2018 .
  37. ^ PyMOTW (Python Module Of The Week), « Обработка исключений, заархивированная 15.09.2015 на Wayback Machine »
  38. ^ «Ответы Google: происхождение проверенных исключений» . Архивировано 6 августа 2011 года . Проверено 15 декабря 2011 .
  39. ^ Спецификация языка Java, глава 11.2. http://java.sun.com/docs/books/jls/third_edition/html/exceptions.html#11.2 Архивировано 8 декабря 2006 г. на Wayback Machine
  40. ^ "OcamlExc - Анализатор неперехваченных исключений для Objective Caml" . Caml.inria.fr. Архивировано 6 августа 2011 года . Проверено 15 декабря 2011 .
  41. ^ «Модула-3 - Типы процедур» . .cs.columbia.edu. 1995-03-08. Архивировано 9 мая 2008 года . Проверено 15 декабря 2011 .
  42. ^ "MindView, Inc Брюса Эккеля: нужны ли для Java проверенные исключения?" . Mindview.net. Архивировано из оригинала на 2002-04-05 . Проверено 15 декабря 2011 .
  43. ^ a b Бьярн Страуструп , Третье издание языка программирования C ++ , Addison Wesley , 1997. ISBN 0-201-88954-4 . С. 375-380. 
  44. Ривз, JW (июль 1996 г.). «Десять руководящих принципов для спецификаций исключений». Отчет C ++ . 8 (7).
  45. Саттер, Херб (3 марта 2010 г.). «Отчет о поездке: март 2010 г. Встреча по стандартам ISO C ++» . Архивировано 23 марта 2010 года . Проверено 24 марта 2010 года .
  46. ^ Mössenböck, Hanspeter (2002-03-25). «Расширенный C #: переменное количество параметров» (PDF) . http://ssw.jku.at/Teaching/Lectures/CSharp/Tutorial/ : Institut für Systemsoftware, Университет Йоханнеса Кеплера в Линце, Fachbereich Informatik. п. 32. Архивировано (PDF) из оригинала 20.09.2011 . Проверено 5 августа 2011 .
  47. ^ Билл Веннерс; Брюс Экель (18 августа 2003 г.). «Проблема с проверенными исключениями: разговор с Андерсом Хейлсбергом, часть II» . п. 2 . Архивировано 18 февраля 2015 года.
  48. Перейти ↑ Bloch 2001: 178 Bloch, Joshua (2001). Руководство по эффективному языку программирования Java . Эддисон-Уэсли Профессионал. ISBN 978-0-201-31005-4.
  49. ^ «Преимущества исключений (Учебники Java ™: основные классы: исключения)» . Download.oracle.com. Архивировано 26 октября 2011 года . Проверено 15 декабря 2011 .
  50. ^ Блох 2001: 172
  51. ^ «Непроверенные исключения - Противоречие (Учебники Java ™: Основные классы: Исключения)» . Download.oracle.com. Архивировано 17 ноября 2011 года . Проверено 15 декабря 2011 .
  52. ^ «Асинхронные исключения в Haskell - Марлоу, Джонс, Моран (ResearchIndex)» . Citeseer.ist.psu.edu. Архивировано 23 февраля 2011 года . Проверено 15 декабря 2011 .
  53. ^ Безопасные асинхронные исключения для Python. «Архивная копия» . Архивировано 30 августа 2006 года . Проверено 7 декабря 2006 .CS1 maint: archived copy as title (link)
  54. ^ «Устаревшая поддержка Java Thread Primitive» . Java.sun.com. Архивировано 26 апреля 2009 года . Проверено 15 декабря 2011 .
  55. ^ Какие условия (исключения) действительно существуют (2008-03-24). «О каких условиях (исключениях) на самом деле идет речь» . Danweinreb.org. Архивировано из оригинала на 1 февраля 2013 года . Проверено 18 сентября 2014 .
  56. ^ "Концепции системы условий" . Franz.com. 2009-07-21. Архивировано из оригинала на 2007-06-28 . Проверено 15 декабря 2011 .
  • Габриэль, Ричард П .; Стил, Гай Л. (2008). Образец эволюции языка (PDF) . LISP50: Празднование 50-летия Lisp. С. 1–10. DOI : 10.1145 / 1529966.1529967 . ISBN 978-1-60558-383-9.
  • Гуденаф, Джон Б. (1975a). Структурированная обработка исключений . Материалы 2-го симпозиума ACM SIGACT-SIGPLAN по принципам языков программирования - POPL '75. С. 204–224. DOI : 10.1145 / 512976.512997 .
  • Гуденаф, Джон Б. (1975). «Обработка исключений: проблемы и предлагаемые обозначения» (PDF) . Коммуникации ACM . 18 (12): 683–696. CiteSeerX  10.1.1.122.7791 . DOI : 10.1145 / 361227.361230 . S2CID  12935051 .
  • Уайт, Джон Л. (май 1979 г.). NIL - Перспектива (PDF) . Материалы конференции пользователей Macsyma 1979 года.

Внешние ссылки

  • Ускоренный курс по глубине структурированной обработки исключений Win32 , Мэтт Пьетрек - Microsoft Systems Journal (1997)
  • Статья Кристофа де Динешена " Обработка исключений C ++ "
  • Статья Брайана Гетца « Исключительные практики »
  • Статья Аруна Удайи Шанкара « Объектно-ориентированная обработка исключений в Perl »
  • Статья Кайла Лаудона « Программирование с исключениями в C ++ »
  • Статья « Непроверенные исключения - противоречие »
  • Слайды конференции « Политика обработки исключений с плавающей точкой» (pdf, стр. 46) , Уильям Кахан
  • Описания из Портлендского репозитория паттернов
  • Нужны ли Java проверенные исключения?