Подтвердить что ты не робот

Когда и как я должен использовать обработку исключений?

Я читаю об обработке исключений. Я получил некоторую информацию о том, что такое обработка исключений, но у меня есть несколько вопросов:

  • Когда бросать исключение?
  • Вместо того, чтобы бросать исключение, можем ли мы использовать возвращаемое значение для указания ошибки?
  • Если я защищу все свои функции блоками try-catch, не уменьшит ли производительность?
  • Когда использовать обработку исключений?
  • Я увидел проект, в котором каждая функция в этом проекте содержала блок try-catch (т.е. код внутри всей функции окружен блоком try-catch). Это хорошая практика?
  • В чем разница между try-catch и __try __except?
4b9b3361

Ответ 1

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

Исключения и обработка ошибок - С++ FAQ или С++ FAQ lite

Как общее правило, генерируйте исключение, когда ваша программа может идентифицировать внешнюю проблему, которая предотвращает выполнение. Если вы получаете данные с сервера и эти данные недействительны, генерируйте исключение. Из дискового пространства? Выбросьте исключение. Космические лучи не позволяют вам запрашивать базу данных? Выбросьте исключение. Но если вы получаете некоторые недопустимые данные из своей собственной программы, не генерируйте исключение. Если ваша проблема исходит из вашего собственного плохого кода, лучше использовать ASSERT для защиты от этого. Обработка исключений необходима для выявления проблем, которые программа не может обрабатывать, и сообщить им о пользователе, поскольку пользователь может их обрабатывать. Но ошибки в вашей программе - это не то, что пользователь может обработать, поэтому сбой программы скажется не намного меньше, чем "Значение answer_to_life_and_universe_and_everything is not 42! Это никогда не должно произойти!!!! 11" исключение.

Выведите исключение, где вы можете сделать что-то полезное с ним, например, отобразить окно сообщения. Я предпочитаю перехватывать исключение один раз внутри функции, которая каким-то образом обрабатывает ввод пользователя. Например, пользователь нажимает кнопку "Уничтожить всех хуннов" и внутри функции annihilateAllHunamsClicked() есть попытка... catch block сказать "Я не могу". Несмотря на то, что уничтожение hunamkind - сложная операция, которая требует вызова десятков и десятков функций, есть только одна попытка... catch, потому что для пользователя это атомная операция - одна кнопка. Исключения в каждой функции являются избыточными и уродливыми.

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

Ответ 2

Исключения полезны в самых разных обстоятельствах.

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

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

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

Модель обработки исключений, используемая на большинстве современных языков, включая С++, известна. Это слишком мощно. Теоретики теперь разработали более совершенные модели, чем полностью открытая модель "бросить что-нибудь" и "возможно, а может и не поймать" ее. Кроме того, использование информации типа для классификации исключений было не очень хорошей идеей.

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

Ответ 3

Лучше всего читать это

Обработка исключений говорила о многом за последние полтора десятилетия. Однако, несмотря на общий консенсус в отношении того, как правильно обрабатывать исключения, разрыв в использовании продолжает существовать. Неправильная обработка исключений легко обнаружить, легко избежать, и это простой показатель качества кода (и разработчика). Я знаю, что абсолютные правила оторвались как близкие или преувеличенные, но, как правило, вы не должны использовать try/catch

http://codebetter.com/karlseguin/2010/01/25/don-t-use-try-catch/

Ответ 4

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

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

3.I думаю, что _try_except является допустимым именем переменной....

Ответ 5

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

Я не согласен с этим аспектом принятого ответа. Утверждение не лучше, чем бросать исключение. Если исключения были пригодны только для ошибок во время выполнения (или "внешних проблем" ), что такое std::logic_error для?

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

Это не похоже на то, что не было предшествующего уровня техники. std::vector, чтобы назвать только одно, выдает исключение логической ошибки, а именно std::out_of_range. Если вы используете стандартную библиотеку и не имеете обработчик верхнего уровня, чтобы улавливать стандартные исключения - если только для вызова того, что() и выйти (3) - то ваши программы подвержены внезапному молчанию, прекращению.

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

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

Ответ 6

Основное отличие:

  • сделайте ошибку для вас.
  • Один из них - это ваш собственный.

    • Например, вы можете сделать выражение 0 divide error. Использование try catch 1. поможет вам при возникновении ошибки. Или вам нужен if a==0 then.. в 2.

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

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

Предлагайте: Просто управляйте собой, когда это просто и в логическом случае.

Ответ 7

Многие пуристы C/С++ вообще исключают исключения. Основные критические замечания:

  • Это медленно - Конечно, это не очень "медленно". Однако, по сравнению с чистым c/С++, накладных расходов довольно много.
  • Он вводит ошибки. Если вы неправильно обрабатываете исключения, вы можете пропустить код очистки в функции, которая генерирует исключение.

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