Какие исключения? - PullRequest
       3

Какие исключения?

4 голосов
/ 03 ноября 2010

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

Вот несколько вопросов:

  • Что является исключением? Какова его самая низкоуровневая композиция в памяти? В .NET я могу думать об этом как о некотором экземпляре объекта некоторого исключения типа . В родном мире, из чего он сделан? Некоторые структуры данных?

  • Кто создает исключение, если исключение явно не выдается программистом, как показывает следующий код? Является ли это частью поддержки, которую обеспечивает определенная языковая среда выполнения?

    SomeException e = new SomeException (); бросить е;

  • Какова рабочая парадигма исключения? Правда ли, что когда происходит какая-то ошибка, во время выполнения языка создается экземпляр соответствующей структуры данных / типа для представления подробностей ошибки?

  • Как мы можем знать все возможные неожиданные ситуации во время выполнения и, таким образом, создать достаточно исключений структур данных / типов для их представления?

Спасибо за ваши ответы.

Ответы [ 7 ]

14 голосов
/ 03 ноября 2010

Ответы на ваши вопросы во многом зависят от того, на каком языке мы говорим.

C вообще не имеет исключений , хотя существуют собственные языковые расширения.
C ++ имеет способ «выбросить» произвольный объект в любой точке вашего кода и «поймать» его где-нибудь выше стек вызовов.
C # имеет способ «выбросить» объекты, полученные из System.Exception, а также «поймать» те, которые находятся выше в стеке. Кроме того, я думаю, что среда выполнения .NET сообщает о некоторых проблемах при создании самого исключения.

  • Что является исключением? Какова его самая низкоуровневая композиция в памяти? В .NET я могу думать об этом как о некотором экземпляре объекта некоторого типа исключения. В родном мире, из чего он сделан? Некоторые структуры данных?

В C ++ это просто произвольный объект, который был создан как другие объекты в коде:

throw 42;                     // throws an int object
throw "blah";                 // throws a char[5] object
throw std::string("arg!");    // throws a std::string object
throw my_type(42);            // throws a my_type object
throw std::exception("doh!"); // throws a std::exception object

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

  • Кто создает исключение, если исключение явно не выдается программистом, как показано в следующем коде? Является ли это частью поддержки, которую обеспечивает определенная языковая среда выполнения?

В C ++ исключения почти могут быть выброшены только из кода. Это может быть ваш собственный код, чужой код, код какой-то библиотеки или код стандартной библиотеки. Но обычно где-то должен быть оператор throw. Есть несколько исключений (без каламбура), например, std::bad_alloc, сгенерированный new (который, вероятно, выдается из оператора throw в коде, но я думаю, что это не обязательно) и std::bad_cast, брошенный из dynamic_cast<>. (Кроме того, следующий стандарт, C ++ 1x, ожидаемый в следующем году, разрешает исключениям каким-то образом пересекать границы потоков, что, вероятно, требует от разработчиков стандартной библиотеки найти способ сохранить исключение в одном потоке и повторно выбросить его из другого. Но я Я довольно смутно от этого.)

    SomeException e = new SomeException(); throw e;

В C ++ вы можете , но вы редко когда-либо захотите это бросить указатели . Вы либо делаете

SomeException e; throw e;

или

throw SomeException();
  • Какая рабочая парадигма исключения? Правда ли, что когда происходит какая-либо ошибка, во время выполнения языка создается экземпляр соответствующей структуры / типа данных, представляющий подробности ошибки?

Есть несколько мест, где стандартная библиотека C ++ генерирует исключения, но кроме этого я могу думать только о двух вышеупомянутых функциях (плюс одна в C ++ 1x), где среда выполнения генерирует исключения "сама".

  • Как мы можем знать все возможные неожиданные ситуации во время выполнения и, таким образом, создавать достаточно структур / типов данных исключений для их представления?

Обычно в C ++ выбрасываются только объекты классов, производных от std::exception, хотя я сталкивался с кодом, который использовал собственную иерархию классов исключений, которая не была внедрена в std::exception. Проблема с иерархией исключений в стандартной библиотеке заключается в том, что ее классы наследуются не виртуально друг от друга, что делает невозможным создание собственной иерархии исключений, скрывающей ту из стандартной библиотеки с использованием множественного наследования. (Например, ваш собственный тип исключения OutOfRange, который наследуется от std::out_of_range, и базовый класс вашего исключения MyException, который наследуется от std::exception.)

В C ++ способ обработки исключений в основном основан на следующих принципах:

  • Пишите код таким образом, чтобы он был защищен от исключений, возникающих в любой момент. Используйте RAII и другие методы для достижения этой цели.
  • Ловите исключения только в тех местах, где вы можете что-то с ними сделать.
  • Бросать исключения только в исключительных случаях.Не используйте их для контроля потока.(Исключения C ++ были разработаны для того, чтобы поставщики могли их реализовать, чтобы минимизировать издержки в неисключительном случае за счет исключительного случая.)
1 голос
/ 03 ноября 2010

Исключения - это эффективный способ обработки ошибок, при котором поток прерывается так, что он больше не может продолжаться.

У исключения есть две стороны: метатель и ловушка.Метатель отвечает за обнаружение ошибки, создает класс исключений, содержащий информацию об ошибке, и «выбрасывает» ее.В значительной степени это все равно, что положить его внутрь шара и бросить мяч - на этом этапе его работа выполнена, и теперь дело до "ловца".

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

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

1 голос
/ 03 ноября 2010

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

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

0 голосов
/ 05 марта 2012

Традиционные методологии обработки ошибок имеют серьезные проблемы:

  • Для возврата кода ошибки из метода требуется каждый вызов для переноса в if, который проверяет наличие ошибки. Одно это почти удвоило бы кодовую базу, и если вы забудете сделать это только один раз, ваша программа больше не будет устойчивой.
  • Код глобальной ошибки (а-ля errno в C) не является поточно-ориентированным.
  • Любой код ошибки - это просто число. Трудно передать более сложные детали о фактической ошибке.
  • Даже если вы используете «структуры исключений», сложно их составить - разные уровни кода могут использовать разные структуры.
  • Etc ...

Исключения позволяют:

  • Передайте богатую информацию об ошибке, поскольку вы бросаете реальные объекты, а не только коды ошибок. Тип объекта не должен быть предопределен и может «соответствовать» ошибке во время выполнения (фактически, одной из основных причин для RTTI в C ++ было определение типа запускаемого типа сгенерированного исключения).
  • Отделить Обнаружение ошибок от обработки ошибок. Обнаружение ошибок выполняется в фрагменте кода, который больше всего знает об ошибке (в нижней части иерархии вызовов), в то время как обработка ошибок может выполняться в гораздо более высоком уровне кода, предположительно, который знает что-то об интерфейсе пользователя.
  • Слоям кода между не нужно знать обо всем этом (но они должны быть написаны "безопасным для исключения" способом).

Что такое исключение?

Объект.

Кто создает исключение ...?

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

В C # с его сборщиком мусора мы можем сохранить оригинальный объект даже во время разматывания стека.

Что такое рабочая парадигма исключения?

Исключения моделируют исключительные события. Если что-то частое, то это , вероятно , не исключение.

Каждый вид ошибки может быть представлен экземпляром другого класса, если это необходимо. Или вы можете представить каждую ошибку с одним и тем же классом. Или что-нибудь промежуточное. Здесь нет жестких правил.

Как мы можем знать все возможные неожиданные ситуации во время выполнения и, таким образом, создавать достаточно структур / типов данных исключений для их представления?

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

0 голосов
/ 03 ноября 2010

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

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

вот полезная серия

http://social.msdn.microsoft.com/Search/en-IN?query=exception+handling&ac=8

0 голосов
/ 03 ноября 2010

Прежде всего, мой ответ только для C ++.В C нет исключений, и я недостаточно знаком с C #, чтобы делать заявления, которые также включают этот язык.

Исключительный объект - это просто объект.Это может быть объект некоторого типа класса, но он также может быть целым числом.Это можно сравнить с возвращаемым значением из функции.Большая разница в том, что хранение исключения в стеке проблематично из-за потока управления, участвующего в обработке исключения.

В C ++ все исключения всегда являются результатом оператора throw.В Microsoft SEH именно среда исполнения языка создает исключения SEH.Таким образом, всегда есть некоторый код, который создает объект исключения.

В C ++ языковая среда выполнения не должна знать обо всех возможных исключениях уровня приложения, которые могут быть выброшены.Он просто должен предоставить механизм, с помощью которого обработчик catch может получить доступ (копию) к генерируемому объекту исключения.Как это достигается, зависит от авторов компилятора.

0 голосов
/ 03 ноября 2010

Исключения являются способом обработки ошибок. Альтернативой являются возвращаемые значения и множество ifs и switch / case.

Это правда, что исключение действует как скрытый переход, но окончательный код легче поддерживать, чем его альтернативу.

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

Также верно, что исключения не должны использоваться неправильно, чтобы их можно было выбросить за каждую мелочь. Если возможно, ошибка должна быть обработана локально. Если нет, создайте исключение, которое будет перехвачено на том уровне, на котором оно может быть обработано.

И последнее замечание: c ++ без исключений - это не c ++, это c с классами

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...