Kiedyś mi doradzono, że program C ++ powinien ostatecznie wyłapać wszystkie wyjątki. Podane wówczas uzasadnienie było zasadniczo takie, że programy, które zezwalają na wyjątki, pojawiają się poza main()
wejściem w dziwny stan zombie. Powiedziano mi to kilka lat temu i z perspektywy czasu uważam, że zaobserwowane zjawisko było spowodowane długim generowaniem wyjątkowo dużych zrzutów rdzenia z przedmiotowego projektu.
W tym czasie wydawało się to dziwne, ale przekonujące. To całkowicie nonsensowne, że C ++ powinien „ukarać” programistów za to, że nie wyłapali wszystkich wyjątków, ale dowody przed mną zdawały się to potwierdzać. W przypadku omawianego projektu programy, które wprowadziły nieprzechwycone wyjątki, wydawały się wchodzić w dziwny stan zombie - lub, jak podejrzewam, przyczyną była teraz, proces pośród niechcianego zrzutu rdzenia jest niezwykle trudny do zatrzymania.
(Dla każdego, kto zastanawia się, dlaczego nie było to wtedy bardziej oczywiste: projekt wygenerował dużą ilość danych wyjściowych w wielu plikach z wielu procesów, które skutecznie przesłaniały dowolny rodzaj aborted (core dumped)
wiadomości, aw tym konkretnym przypadku pośmiertne badanie zrzutów rdzenia nie było jest to ważna technika debugowania, dlatego nie rzucano dużo na zrzuty rdzenia. Problemy z programem zwykle nie zależały od stanu nagromadzonego na podstawie wielu zdarzeń w czasie przez program długo działający, ale raczej początkowe dane wejściowe do programu krótkotrwałego (< 1 godzina), więc bardziej praktyczne było ponowne uruchomienie programu z tymi samymi danymi wejściowymi z kompilacji debugowania lub w debugerze, aby uzyskać więcej informacji.)
Obecnie nie jestem pewien, czy istnieje jakaś poważna zaleta lub wada wychwytywania wyjątków wyłącznie w celu zapobiegania wyjściu wyjątków main()
.
Niewielką zaletą, jaką mogę wymyślić, aby pozwolić na wyjątki, aby zniknęły w przeszłości, main()
jest to, że powoduje std::exception::what()
to wydrukowanie wyniku na terminalu (przynajmniej w przypadku programów skompilowanych gcc w systemie Linux). Z drugiej strony jest to trywialne do osiągnięcia przez wychwycenie wszystkich wyjątków wynikających z std::exception
i wydrukowanie wyniku, std::exception::what()
a jeśli pożądane jest wydrukowanie wiadomości z wyjątku, który z niej nie pochodzi std::exception
, należy ją złapać przed wyjściem main()
w celu wydrukowania wiadomość.
Skromną wadą, jaką mogę wymyślić, aby pozwolić na wyjątki, aby się wybić, main()
jest to, że mogą powstawać niepożądane zrzuty rdzeni. W przypadku procesu używającego dużej ilości pamięci może to być dość uciążliwe, a kontrolowanie zachowania zrzutu pamięci z programu wymaga wywołań funkcji specyficznych dla systemu operacyjnego. Z drugiej strony, jeśli pożądany jest zrzut pamięci i wyjście, można to w dowolnym momencie osiągnąć przez wywołanie, std::abort()
a wyjście bez zrzutu pamięci można w dowolnym momencie wywołać std::exit()
.
Anegdotycznie nie sądzę, żebym kiedykolwiek widział domyślną what(): ...
wiadomość drukowaną przez szeroko rozpowszechniany program po awarii.
Jakie są, jeśli w ogóle, mocne argumenty przemawiające za lub przeciw dopuszczeniu wyjątków C ++ main()
?
Edycja: Na tej stronie jest wiele ogólnych pytań dotyczących obsługi wyjątków. Moje pytanie dotyczy w szczególności wyjątków w C ++, których nie można obsłużyć i które doprowadziły do końca main()
- być może można wydrukować komunikat o błędzie, ale jest to natychmiastowy błąd zatrzymania.