Я спорил с коллегой об опасности использования catch(...)
Он указывал мне на возможное использование, строго подразумевая что нибудь catch(...)
сопровождается следом / журналом: чтобы помочь определить происхождение некоторых неуправляемых исключений.
Я лично скептически отношусь к этому. Знаете ли вы о каком-либо явном безопасном использовании catch(...)
РЕДАКТИРОВАТЬ: Для тех, кто интересуется дебатами, мой коллега только что указал мне на этот вопрос на сайте программистов.
Исключения часто злоупотребляют. Почти всегда это чрезмерное использование сопровождается всеобъемлющими утверждениями. Обычно это признак плохого использования и понимания исключений. Я никогда не рекомендую это. К сожалению, в каком-то (плохом) месте, где я работал, другие люди применяли эту политику.
Ярчайшее интересное безопасное использование catch(...)
я знаю о том, чтобы разгрузить код для обработки различных исключений для совместно используемой функции:
void handle_error() {
try {
throw;
} catch (TiresomelyPedanticException &) {
# lah lah I don't care
return;
} catch (InterestingException &) {
log_something();
throw;
}
// etc. This catch chain may *or may not* need a catch(...)
// of its own, it depends whether part of its job is to
// deal with the "miscellaneous" case.
}
Вы используете функцию как это:
try {
blah();
} catch(...) {
handle_error();
}
… где-нибудь еще …
try {
something_that_throws_the_same_exceptions_as_blah();
} catch (...) {
handle_error();
}
Однако приведенный выше шаблон может показаться чем-то вроде C ++ 03. В C ++ 11 написать лямбду захвата так легко, что следующее может быть более полезным для вызывающих, и нет catch(...)
в шаблоне:
template <typename Func>
auto do_and_handle_error(Func f) -> decltype(f()) {
try {
return f();
} // catch chain goes here
}
Используйте это как:
do_and_handle_error(blah);
или, как на самом деле окажется необходимым, когда blah
принимает аргументы:
do_and_handle_error([&](void) { return blah(arg1,arg2); });
Скучное использование catch(...)
является гарантией того, что стек будет размотан до завершения программы:
int my_main() {
RAIIClass some_object_i_want_to_get_destroyed_no_matter_what;
some_code_that_might_throw();
return 0;
}
int main() {
try {
return my_main();
} catch (...) {
throw;
}
}
Без улова стандарт оставляет его либо неопределенным, либо определяемым реализацией, независимо от того, some_object
уничтожается, если выдает код.
Следующее всегда безопасно:
try
{
some_local_stuff();
}
catch (...)
{
clean_up_local_stuff();
throw;
}
Другими словами, всеобъемлющее catch
Блок должен использоваться только в сочетании с перебрасыванием того же самого исключения или сохранением указателя исключения для транспортировки исключения.
Блоки Catch, которые полностью исключают исключение, должны конкретно указывать тип исключения, которое они обрабатывают.