Что вы используете для исключения С++?

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

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

В этом вопросе мне интересно узнать:

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

Ответ 1

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

Допустимый пример: сервер, на котором работает ваш код, недоступен, поэтому ваша служба не может ничего значимого.

Пример, который означает, что я раздражен вашим кодом: пользователь вводил число, большее 100, в качестве входа в вашу функцию, которая ожидает число <= 100.

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

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

Ответ 2

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

Что делает это трудным, так это то, что низкоуровневый код должен решить, какой исключительный, но только код высокого уровня знает, является ли данная ошибка исключительной. Например, рассмотрим функцию, загружающую значок. Что он должен делать, когда он терпит неудачу? Только код вызова знает, является ли критическая ошибка (программа НЕОБХОДИМА, что значок для продолжения) или нет (значок просто декоративен).

Практические вопросы, как правило, превосходят элегантность. Конструкторы, которые не могут выполнить исключения, чтобы RAII работала. С другой стороны, деструкторы не должны бросать исключения. Тогда есть все барьеры, по которым вы не можете позволить исключение летать. Например, в Windows это небезопасно, чтобы исключение распространялось из обратного вызова ОС (например, оконная процедура). Если вы многопоточны, необработанное исключение в одном из ваших рабочих потоков приведет к разрушению процесса, не отрываясь и не называя дурма на других ваших потоках. Драйверы устройств и код ядра обычно не могут использовать исключения в стиле С++ из-за ограничений поискового вызова. COM не играет хорошо с исключениями.

Ответ 3

Хотя многие люди рассматривают исключения на С++ действительно как "нечто исключительное", я нахожу их невероятно удобными для выполнения основной проверки/проверки ошибок, в основном на уровне приложений (как в не в ядре библиотека)

Например, я бы предпочел написать

try
{
  MethodA();
  MethodB();
  //.. a whole lot of other methods crucial to succeed for app initialization
}
catch( const SomeException& e )
{
  //show user the critical error contained in e
  return 1;
}

затем записывая

if( !MethodA() )
{
  //retrieve and show error
  return 1;
}
if( !MethodB() || !MethodC() )
{
  //retrieve and show error
  return 1;
}
//etc

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

В прошлый раз я их использовал:

throw "Сообщение об ошибке Constant (соответствующее)"

при возникновении серьезного состояния.

Несколько раз я задерживал дополнительные данные в глобальных переменных, но это было до того, как я написал многопоточный код. Я должен был бы переосмыслить это (очевидно).

Не то, чтобы я рекомендовал эту технику больше.