многоточие попробуйте поймать на c ++

Можно ли использовать команду с многоточием для выявления всех ошибок, которые могут привести к сбою? Есть ли аномалии?

try
{
//some operation
}
catch(...)
{
}

person ssk    schedule 12.10.2011    source источник
comment
Во всех ответах есть небольшая неточность: в C ++ вы можете выбросить что угодно, а не только исключения, читать ответы так, как если бы что-нибудь было брошено использовалось вместо всех исключений.   -  person David Rodríguez - dribeas    schedule 12.10.2011
comment
Если вы намерены добавить комплексный обработчик, чтобы предотвратить сбой вашей программы, не делайте этого. Вместо этого исправьте ошибки в вашем коде.   -  person John Dibling    schedule 12.10.2011
comment
@David: Но то, что вы выбрасываете, становится исключением, даже если это int (1);   -  person Martin York    schedule 12.10.2011


Ответы (4)


Нет, он будет ловить только исключения C ++, а не такие вещи, как segfault, SIGINT и т. Д.

Вам необходимо прочитать и понять разницу между исключениями C ++ и, если не хватает лучшего слова, «сигналами в стиле C» (такими как SIGINT).

person John Carter    schedule 12.10.2011
comment
В зависимости от компилятора и его настроек он также может перехватывать исключения SEH в Windows (которые включают такие вещи, как нарушения доступа). - person Cat Plus Plus; 12.10.2011

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

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


Дополнение: прочтите эту статью в "Старом новом", чтобы получить дополнительную информацию.

person Vlad    schedule 12.10.2011
comment
Хотя для логирования это все же пригодится. Просто не забудьте завершить блок catch оператором throw;, чтобы продолжить бросок. - person Mooing Duck; 12.10.2011
comment
@MooingDuck: Я бы лучше не регистрировался в catchall-block. Вы никогда не знаете, насколько точно повреждено состояние вашей программы, и лучше сделать как можно меньше, чтобы предотвратить, например, повреждение пользовательских данных. - person Vlad; 12.10.2011
comment
@MooingDuck: да :-) Посмотрите статью, на которую я ссылаюсь. - person Vlad; 12.10.2011
comment
Хорошая статья. У меня был целый аргумент о том, что не повредит попробовать набрать текст, пока я не понял, что запись в std::cerr в состоянии сбоя может перезаписать буфер потока RIAA или межпроцессную память, которая затем будет сброшена во время раскрутки стека. Значит ты прав. Сведите к минимуму нанесенный ущерб. Не используйте catch (...). - person Mooing Duck; 12.10.2011
comment
@MooingDuck: действительно, в Visual C ++ catch(...) ловит SE (!), поэтому программа потенциально находится в очень плохом состоянии. - person Vlad; 13.10.2011

Это обработчик Catch All.
Он перехватывает все исключения C ++, возникающие из блока try. Он не улавливает segfault и другие сигналы, которые вызывают сбой вашей программы.

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

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

person Alok Save    schedule 12.10.2011
comment
Это отличная идея для регистрации. Только не забудьте продолжить бросок с throw; - person Mooing Duck; 12.10.2011
comment
@MooingDuck: Не совсем. Вы теряете информацию о типе, все, что вы можете зарегистрировать, это упс, исключение, извините. Для этого лучше поймать std::exception в обработчике верхнего уровня. - person Cat Plus Plus; 12.10.2011
comment
@CatPlusPlus: Влад убедил меня, что вход в неизвестное состояние опасен. Комментарий отозван. - person Mooing Duck; 12.10.2011
comment
Я думаю, что в принципе неправильно говорить, что использовать его - плохая идея. Я бы сравнил универсального оператора с катапультным креслом в военном самолете. Да, вы бы предпочли никогда не использовать его, но когда что-то идет не так, как надо, использовать его все равно лучше, чем кататься на нем в огне. - person Jerry Coffin; 12.10.2011
comment
@JerryCoffin: Ни один из ответов на самом деле не указывал на то, что его использование на самом деле не является хорошей практикой, я пытался, возможно, слова не оправдали / не передали то, что я хотел, но, тем не менее, я пытался передать правильные вещи. Не знаю, голосуют ли пользователи мозгом или менталитетом толпы, но я получил 3 отрицательных голоса за то, что сказал правильную, но не очень популярную вещь. - person Alok Save; 12.10.2011
comment
@Jerry: посмотрите blogs.msdn.com/b /oldnewthing/archive/2009/11/13/9921676.aspx по некоторым причинам, почему делать что-то в catch_all - это плохо. Пример: исключение могло произойти в середине выделения блока кучи, поэтому любая попытка регистрации может привести к непредсказуемым вещам (включая запуск назальных демонов). - person Vlad; 12.10.2011
comment
Ага, я понимаю, к чему вы клоните, и согласен с основной идеей, но хотел бы, чтобы она была сформулирована лучше. Я тоже не думаю, что @Vlad прав. Да, это может теоретически полностью выйти из строя - точно так же, как любой вызов функции может вызвать переполнение стека и ужасный сбой. Оба, однако, достаточно часто полезны, чтобы быть полезными инструментами. - person Jerry Coffin; 13.10.2011
comment
@Jerry: внутри пункта catch(...) шансы, что что-то пошло не так, довольно высоки. В частности, вполне разумны шансы, что куча находится в несогласованном состоянии или принята глобальная блокировка ввода-вывода. - person Vlad; 13.10.2011
comment
@Vlad: Не совсем. Предложение catch(...) вызывается только для исключений C ++. Чтобы вызвать вызов, стек должен быть достаточно последовательным, чтобы можно было проследить обратную связь и найти обработчики catch. По пути разматывание стека будет (пытаться) уничтожить местных жителей. Обычно это связано с некоторыми deletes, поэтому, если куча действительно повреждена, она, вероятно, выйдет в ОС до того, как будет достигнут обработчик. В этом обработчике шансы на то, что система ужасно повреждена, на самом деле довольно малы. В статье, которую вы связали, говорилось о SetUnhandledExceptionFilter - это совершенно другая ситуация. - person Jerry Coffin; 13.10.2011
comment
@ Джерри: Не совсем. :) В Windows / Visual C ++ catch(...) ловит SEH, который может быть брошен в довольно неприятные моменты. (Так что между catch(...) и SetUnhandledExceptionFilter нет такой большой разницы.) Здесь есть комментарий ТАК предполагая, что в Linux catch(...) может поймать сигнал (если я правильно понял), но я не смог найти никаких упоминаний об этом в Интернете. - person Vlad; 13.10.2011
comment
@Vlad: Вопрос помечен как C ++. Захват SEH произошел в VC ++ 6, но это, безусловно, не следует путать с C ++. - person Jerry Coffin; 13.10.2011
comment
@Jerry: ну, Windows по-прежнему остается самой популярной настольной платформой, верно? Поэтому мы не можем сказать, что VC ++ не считается. Но что ж, я должен признать, что это соображение лежит за пределами башни из слоновой кости стандартного C ++ (вздох). (AFAIK поведение catch такое же и в VC ++ 2010.) - person Vlad; 13.10.2011
comment
@Vlad: Вот моя точка зрения: поведение catch не то же самое в VC ++ 2010, VC ++ 2008 или чем-либо еще, начиная с VC ++ 6. возможно получить поведение, подобное VC ++ 6, если вы достаточно сильно хотите, но это не происходит по умолчанию и не происходит уже много лет. - person Jerry Coffin; 13.10.2011
comment
@Jerry: быстрый поиск в Google нашел мне link, из которого следует, что при некоторых обстоятельствах поведение в 2010 году было таким же. Кодируя часть большого проекта, нужно быть осторожным. - person Vlad; 13.10.2011
comment
@Vlad: Вы читали статью по ссылке? Это в точности соответствует тому, что я сказал: возможно получить такое поведение, если вы достаточно постараетесь, но по умолчанию этого не происходит. Никто, чей IQ выше, чем их размер шляпы, даже подумал бы о том, чтобы сделать это, за исключением того, чтобы заставить работать старый код, написанный для VC ++ 6 или более ранней версии (для достаточно свободного определения работы). - person Jerry Coffin; 13.10.2011
comment
@Jerry: по сути, последний проект C ++, над которым я работал, скомпилирован с /EHa. Но наш архитектор в шляпе не надел. (Возможно, потому, что он был преобразован из какого-то старого кода.) - person Vlad; 13.10.2011

Он ловит все, что бросается, не ограничивается исключениями. Он не обрабатывает такие вещи, как утверждения отладки Windows, системные сигналы, ошибки segfaults.

TEST(throw_int) {
    try {
        throw -1;
    } catch (std::exception &e) {
        std::cerr << "caught " << e.what() << std::endl;
    } catch (...) {
        std::cerr << "caught ..." << std::endl;
    }
}

Однако использование целого числа не рекомендуется. Лучше скинуть то, что унаследовано от std::exception.

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

int main(int argc, char ** argv) {
    try {
        // ...
    } catch (std::exception &e) {
        std::cerr << "error occured: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}
person Tom Kerr    schedule 12.10.2011