Обработка исключений - PullRequest
       7

Обработка исключений

2 голосов
/ 09 декабря 2008

Является ли обработка структурированных исключений плохой? Как правильно обрабатывать исключения?

РЕДАКТИРОВАТЬ: Обработка исключений в .NET с использованием C #.

У меня обычно есть набор определенных классов исключений (DivideByZeroException, ArrayTypeMismatchException), и у меня нет общего «catch (Exception ex)».

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

Ответы [ 5 ]

6 голосов
/ 09 декабря 2008

Я не уверен, что вы подразумеваете под «структурной обработкой исключений».

Худшее, что можно сделать при обработке исключений, - это «проглотить» исключение или обработать его молча.

НЕ делайте этого:

try {
   ...
}
catch (Exception e) {
   //TODO: handle this later
}

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

3 голосов
/ 09 декабря 2008

Catch операторов + Stack следы. Никогда не перехватывайте исключение, не печатая трассировку стека, вам или кому-либо еще придется извлекать этот код снова и помещать трассировки стека в блок Catch при возникновении ошибки, когда ваши файлы журнала либо пусты, либо расплывчаты.

1 голос
/ 09 декабря 2008

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

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

Одно можно сказать наверняка, не смешивайте два подхода в одном компоненте ...

1 голос
/ 09 декабря 2008

Моя рекомендация:

Не поймать исключение, если:

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

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

0 голосов
/ 09 декабря 2008

Я не программист Windows, но мне кажется, что использование структурированной обработки исключений для обработки аппаратных исключений, таких как программные исключения, означает, что:

  • Ваш код выполняет то, что в стандарте C ++ вызывает неопределенное или определяемое реализацией поведение (например, деление на ноль).
  • Windows определяет, что при включенном SEH в этом случае выдается исключение.
  • Вы используете этот факт для перехвата исключения и / или выполнения обработчика завершения.

Итак, ИМО задает следующие вопросы:

  • Является ли ваша задача программирования в природе, которую стандарт C ++ не может обработать? (или может обрабатывать только способом, который заметно уступает тому, что вы получаете, допуская аппаратное исключение).
  • Вам действительно нужно действовать, когда ваш код нестандартен?
  • Можете ли вы написать свой код, чтобы он не вызывал аппаратные исключения?

Если ответы «да», «да», «нет», то необходима обработка структурированных исключений. В противном случае вы сможете избежать этого, и в этом случае вы, вероятно, захотите. Написание кода, исключающего исключения, сложнее, поэтому чем сильнее исключение, тем лучше вы можете его предложить. Код, который может делиться на ноль с помощью SEH, не дает гарантии nothrow, хотя, возможно, с небольшим изменением дизайна, чтобы вызывающие абоненты не передавали ему пустые данные, это могло бы быть сделано. Но если функция уже должна генерировать исключения по другим причинам, то, возможно, и их выброс для аппаратных ловушек может не ухудшить ситуацию.

Один примечательный особый случай - распределение памяти. Не уверен, что .NET делает это, но в linux распределение завершается неудачно, только если для размещения недостаточно виртуального адресного пространства. Физическая память выделяется при первом использовании и вызывает аппаратное исключение, если его недостаточно. Поскольку выделение памяти составляет , предполагается для выброса std :: bad_alloc в случае сбоя, и реализация не может реализовать это требование стандарта, может быть в том, что в некоторых случаях преобразование аппаратного исключения в Программное обеспечение - правильная вещь. Однако это аппаратное исключение может возникать в неожиданных местах (в том числе в подпрограммах, которые вы считали не слишком быстрыми), поэтому по-прежнему может быть невозможно обработать изящно, именно поэтому ядро ​​linux сбрасывает, а не выбрасывает. На практике все, что инициализируется полностью, приводит к сбою его конструктора, который часто достаточно близок к распределению, что вместо этого было бы полезно программное исключение.

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