Може ли многоточие try-catch да се използва за улавяне на всички грешки, които могат да доведат до срив? Има ли някакви аномалии?
try
{
//some operation
}
catch(...)
{
}
Може ли многоточие try-catch да се използва за улавяне на всички грешки, които могат да доведат до срив? Има ли някакви аномалии?
try
{
//some operation
}
catch(...)
{
}
Не, ще хваща само C++ изключения, а не неща като segfault, SIGINT и т.н.
Трябва да прочетете и разберете разликата между изключенията на C++ и при липса на по-добра дума, сигнали в стил "C" (като SIGINT).
Ако кодът в блока try/catch се срине по някакъв начин, програмата така или иначе е в състояние, което не може да се възстанови. Не трябва да се опитвате да предотвратите срива, най-доброто, което програмата може да направи, е просто да остави процеса да се срине.
"Аномалията" е във факта, че вашият код улавя само изключенията, а не грешките. Дори ако кодът е защитен от изключения (което може да не е така, ако се опитвате да заобиколите грешките му чрез блок try/catch), всяка друга вътрешна грешка може да доведе програмата до непоправимо състояние. Просто няма начин да защитите програмата от него.
Допълнение: вижте тази статия в „Старото ново нещо“ за някои прозрения.
catch
с оператор throw;
, за да продължите хвърлянето.
- person Mooing Duck; 12.10.2011
std::cerr
в състояние на грешка може да презапише буфера на RIAA поток или междупроцесна памет, която след това ще бъде изчистена по време на размотаване на стека. Значи си прав. Минимизирайте нанесените щети. Не използвайте catch (...)
.
- person Mooing Duck; 12.10.2011
catch(...)
улавя SE (!), така че програмата е потенциално в много лошо състояние.
- person Vlad; 13.10.2011
Това е Catch All манипулатор.
Той улавя всички C++ изключения, хвърлени от блока try. Не улавя segfault и други сигнали, които причиняват срив на програмата ви.
Докато го използвате, трябва да поставите този манипулатор в края на всички други специфични манипулатори за улавяне или всички ваши изключения ще бъдат уловени от този манипулатор.
Лоша идея е да използвате catch all handler, защото той просто маскира вашите проблеми и скрива неспособността на програмите, като улавя всички (дори неразпознати) изключения. Ако се сблъскате с такава ситуация, по-добре оставете програмата да се срине и създайте дъмп за срив, който можете да анализирате по-късно и да разрешите корена на проблема.
throw;
- person Mooing Duck; 12.10.2011
std::exception
в манипулатора от най-високо ниво за това.
- person Cat Plus Plus; 12.10.2011
catch(...)
шансовете нещо да се е объркало са доста големи. По-специално, шансовете, че купчината е в непоследователно състояние или е взето глобално I/O заключване, са разумни.
- person Vlad; 13.10.2011
catch(...)
се извиква само за C++ изключения. За да бъде извикан, стекът трябва да е достатъчно последователен, за да се проследи обратно, за да се намерят манипулаторите на catch. По пътя размотаването на стека ще (се опита да) унищожи местните жители. Това обикновено включва някои delete
s, така че ако купчината наистина е повредена, вероятно ще излезе от операционната система, преди да бъде достигнат манипулаторът. В този манипулатор шансовете системата да е ужасно корумпирана всъщност са доста малки. Статията, която сте свързали, говори за SetUnhandledExceptionFilter -- което е коренно различна ситуация.
- person Jerry Coffin; 13.10.2011
catch(...)
хваща SEH, който може да бъде хвърлен в доста неприятни моменти. (Така че няма толкова голяма разлика между catch(...)
и SetUnhandledExceptionFilter
.) Тук има коментар ТАКА предполага, че на Linux catch(...)
може да улови сигнал (ако съм го разбрал правилно), но не можах да намеря никакви препратки за това в Интернет.
- person Vlad; 13.10.2011
/EHa
. Нашият архитект обаче не носеше шапката. (Може би защото е преобразуван от някакъв стар код.)
- person Vlad; 13.10.2011
Той улавя всичко, което е хвърлено, не се ограничава до изключения. Той не обработва неща като твърдения за отстраняване на грешки в Windows, системни сигнали, грешки в сегментите.
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;
}