2013-07-24 8 views
7

Czytam „C++ Programming Language 4. wydanie” Książka i mam pytanie odnośnie akapitu o obsługę wyjątków:Throwing wyjątek podczas obsługi wyjątku

Istnieją przypadki, w których obsługa wyjątków muszą być opuszczone do mniej subtelnych technik obsługi błędów. Zasady są następujące:

  • Nie wyrzucaj wyjątku podczas obsługi wyjątku.
  • Nie wyrzucaj wyjątku, którego nie można przechwycić.

Jeśli złapie Cię implementacja obsługi wyjątków, to zakończy Twój program.

Czy ktoś może podać mi przykład pierwszej wersji? Tylko coś takiego przychodzi mi na myśl, ale jest to poprawny kod zgodny z g ++:

try 
{ 
    throw 1; 
} 
catch(...) 
{ 
    try 
    { 
     throw 2; 
    } 
    catch(...) 
    { 
     cout << "OK"; 
    } 
} 
+2

nie należy zakładać, że coś jest ważne i/lub robi to, co myślisz, że tylko dlatego, że skompilowany! 'C++' ma pojęcie [* niezdefiniowane zachowanie *] (http://blog.regehr.org/archives/213), które z grubsza tłumaczy się jako "jeśli zrobisz coś nieważnego, wszystkie zakłady są wyłączone". Może się zawiesić, może działać, może wydawać się działać, ale wysłać wszystkie numery kart kredytowych do nigeryjskich książąt. Uwaga Nie mówię, że ten konkretny przypadek jest (myślę, że to nie jest UB, tylko niebezpiecznie blisko), ale nie myśl, że "skompilowałeś, to jest w porządku". – BoBTFish

+3

Nie mogę się zgodzić z pierwszym z nich, ale mogę serdecznie zgodzić się z drugim. Istnieje * wiele * razy catch-blocks może wyrzucać wyjątki, w tym ten sam wyjątek (przez 'throw;'). – WhozCraig

Odpowiedz

12

To trochę mylące; dobrze jest rzucić z obsługi wyjątków (co rozumiem przez "podczas obsługi wyjątku"), o ile istnieje inny program obsługi, który mógłby go przechwycić.

Problem polega na wyrzuceniu wyjątku z destruktora obiektu, który jest niszczony podczas rozwijania stosu. W takim przypadku istnieją dwa nieobsługiwane wyjątki, a zwykły mechanizm wyjątków może obsłużyć tylko jeden; więc odpowiedzią jest wywołanie terminate.

Przykład:

struct dodgy {~dodgy() {throw "Don't do this!";}}; 

try { 
    dodgy d; 
    throw 1; 
} catch (...) { 
    // Never reached: destroying `d` killed the program. 
} 
+0

+1 dla punktu dotyczącego zachowania destruktora w środowisku z wieloma rzutami. Nieczęsto uważany, ale często problem. Fajna notatka. – WhozCraig

+0

Dzięki, znalazłem również znacznie bardziej szczegółowe wyjaśnienie w standardzie - to 15.5.1/1. – Quentin

+0

Możesz użyć 'std :: uncaught_exception', aby sprawdzić, czy wyrzucenie wyjątku zabije program. –