Я читаю об обработке исключений. Я получил некоторую информацию о том, что такое обработка исключений, но у меня есть несколько вопросов:
- Когда вызывать исключение?
- Можем ли мы использовать возвращаемое значение, чтобы указать ошибку, вместо того, чтобы генерировать исключение?
- Если я защищу все свои функции блоками try-catch, не снизится ли это производительность?
- Когда использовать обработку исключений?
- Я видел проект, в котором каждая функция в этом проекте содержала блок try-catch (т.е. код внутри всей функции окружен блоком try-catch). Это хорошая практика?
- В чем разница между try-catch и __try __except?
c++
windows
exception
exception-handling
Умеша М.С.
источник
источник
Ответы:
Вот довольно подробное руководство по исключениям, которое, я считаю, необходимо прочитать:
Исключения и обработка ошибок - C ++ FAQ или C ++ FAQ lite
Как правило, генерируйте исключение, когда ваша программа может идентифицировать внешнийпроблема, препятствующая исполнению. Если вы получаете данные с сервера и эти данные недействительны, вызовите исключение. Нет места на диске? Выбросить исключение. Космические лучи мешают вам запрашивать базу данных? Выбросить исключение. Но если вы получаете некорректные данные внутри вашей собственной программы - не создавайте исключения. Если ваша проблема связана с вашим собственным плохим кодом, лучше использовать ASSERT для защиты от нее. Обработка исключений необходима для выявления проблем, с которыми программа не может справиться, и для того, чтобы сообщить им о пользователе, поскольку пользователь может их решить. Но ошибки в вашей программе - это не то, с чем может справиться пользователь, поэтому сбой программы скажет не намного меньше, чем «Значение answer_to_life_and_universe_and_everything не равно 42! Этого не должно происходить !!!! 11».
Перехватить исключение, в котором вы можете сделать с ним что-нибудь полезное, например, отобразить окно сообщения. Я предпочитаю перехватывать исключение один раз внутри функции, которая каким-то образом обрабатывает ввод пользователя. Например, пользователь нажимает кнопку «Аннигилировать все хунамы», а внутри функции annihilateAllHunamsClicked () есть блок try ... catch, чтобы сказать «Я не могу». Хотя уничтожение hunamkind - сложная операция, требующая вызова десятков и десятков функций, есть только одна попытка ... ловушка, потому что для пользователя это атомарная операция - одно нажатие кнопки. Проверки исключений в каждой функции излишни и уродливы.
Кроме того, я не могу порекомендовать достаточно хорошо ознакомиться с RAII - то есть убедиться, что все инициализированные данные уничтожаются автоматически. И этого можно достичь, инициализировав как можно больше в стеке, а когда вам нужно что-то инициализировать в куче, используйте какой-то умный указатель. Все, что инициализировано в стеке, будет автоматически уничтожено при возникновении исключения. Если вы используете немые указатели в стиле C, вы рискуете утечкой памяти при возникновении исключения, потому что нет никого, кто мог бы очистить их после исключения (конечно, вы можете использовать указатели в стиле C как члены вашего класса, но убедитесь, что они позаботились в деструкторе).
источник
fclose
then!). Это не даст вам полной трассировки стека.Исключения полезны во множестве обстоятельств.
Во-первых, есть некоторые функции, в которых стоимость вычисления предварительного условия настолько высока, что лучше просто выполнить вычисление и прервать выполнение с исключением, если обнаружится, что предварительное условие не выполнено. Например, вы не можете инвертировать сингулярную матрицу, однако, чтобы вычислить, является ли она сингулярной, вы вычисляете определитель, что очень дорого: в любом случае это может быть сделано внутри функции, поэтому просто «попробуйте» инвертировать матрицу и сообщить ошибка, если вы не можете выбросить исключение. Это в основном исключение как отрицательное предварительное условие. .
Есть и другие случаи, когда ваш код уже сложен и передача информации об ошибках вверх по цепочке вызовов затруднена. Отчасти это связано с тем, что C и C ++ имеют сломанные модели структур данных: есть другие, более эффективные способы, но C ++ не поддерживает их (например, использование монад в Haskell). Это использование в основном я не мог беспокоиться о том, чтобы сделать это правильно, поэтому я выброшу исключение : это не правильный путь, но он практичный.
Затем есть основное применение исключений: чтобы сообщить, когда внешние предварительные условия или инварианты, такие как достаточные ресурсы, такие как память или дисковое пространство, недоступны. В этом случае вы обычно завершаете программу или ее основную часть, и исключением является хороший способ передачи информации о проблеме. Исключения C ++ были разработаны для сообщения об ошибках, препятствующих продолжению работы программы .
Модель обработки исключений , используемая в большинстве современных языков , включая C ++ является известным разбиться. Это слишком мощно. К настоящему времени теоретики разработали более совершенные модели, чем полностью открытая модель «бросить что-нибудь» и «может быть, а может и не поймать». Кроме того, использование информации о типе для классификации исключений было не очень хорошей идеей.
Поэтому лучшее, что вы можете сделать, - это экономно генерировать исключения, когда есть реальная ошибка, и когда нет другого способа справиться с ней и перехватывать исключения как можно ближе к точке выброса .
источник
Я не согласен с этим аспектом принятого ответа . Утверждение не лучше, чем выброс исключения. Если исключения подходят только для ошибок времени выполнения (или «внешних проблем»), для чего
std::logic_error
?Логическая ошибка почти по определению является условием, препятствующим продолжению выполнения программы. Если программа представляет собой логическую конструкцию и условие возникает вне области этой логики, как она может продолжаться? Соберите входные данные, пока можете, и выбросьте исключение!
Это не похоже на отсутствие предшествующего уровня техники.
std::vector
, чтобы назвать только одно, выдает исключение логической ошибки, а именноstd::out_of_range
. Если вы используете стандартную библиотеку и у вас нет обработчика верхнего уровня для перехвата стандартных исключений - хотя бы для вызова what () и exit (3) - тогда ваши программы подвергаются внезапному молчаливому завершению.Макрос assert - гораздо более слабый защитник. Восстановления нет. Если, конечно, вы не запускаете отладочную сборку, и в этом случае выполнение не выполняется . Макрос assert относится к эпохе, когда вычисления выполнялись на 6 порядков медленнее, чем сегодня. Если у вас возникнут проблемы с проверкой логических ошибок, но не с тем, чтобы использовать этот тест, когда он важен, в рабочей среде, вам лучше быть уверенным в своем коде!
Стандартная библиотека обеспечивает исключения логических ошибок и использует их. Они существуют по какой-то причине: потому что логические ошибки случаются и являются исключительными. Просто потому, что утверждения функций C не являются основанием полагаться на такой примитивный (и, возможно, бесполезный) механизм, когда исключение намного лучше справляется с задачей.
источник
Лучшее чтение для этого
Об обработке исключений много говорилось за последние полтора десятилетия. Однако, несмотря на общее мнение о том, как правильно обрабатывать исключения, различия в использовании продолжают существовать. Неправильную обработку исключений легко обнаружить, легко избежать и это простой показатель качества кода (и разработчика). Я знаю, что абсолютные правила кажутся ограниченными или преувеличенными, но, как правило, вам не следует использовать try / catch
http://codebetter.com/karlseguin/2010/01/25/don-t-use-try-catch/
источник
try
/catch {}
?1. В код включена проверка исключения, когда есть возможность получить исключение в результате или где-то посередине проблемы.
2. Используйте блок try-catch только в тех случаях, когда это необходимо. Использование каждого блока try-catch добавляет дополнительную проверку условий, что, безусловно, снижает оптимизацию кода.
3. Я думаю, что _try_except - допустимое имя переменной ....
источник
Основное различие:
один - вы делаете свое собственное.
Например, у вас может быть выражение
0 divide error
. Использование try catch1.
поможет вам в случае возникновения ошибки. Или вам нужноif a==0 then..
в2.
Если вы не пытаетесь поймать исключение, я не думаю, что это быстрее, его просто обойти, если
error
это произойдет, это будетthrew
для внешнего обработчика.Принятие себя означает, что проблема не заходит дальше, тогда вы получаете преимущество в скорости во многих случаях, но не всегда.
Совет: просто ведите себя, когда это просто и логично.
источник
Многие пуристы C / C ++ вообще не одобряют исключений. Основные критические замечания:
Вместо этого проверяйте возвращаемое значение / код ошибки каждый раз, когда вызываете функцию.
источник