Nie używaj wyjątków w destruktorze
Objawy: program się gwałtownie wywala, niekiedy w zrzucie stosu można się dopatrzeć informacji o wywołaniu funkcji terminate, na Unixach mamy informację o SIGABORT (sygnale 134).
Większość takich błędów jest spowodowana rzuceniem wyjątku przez destruktor jakiegoś obiektu, który to destruktor został zawołany w czasie zwijania kontekstu, gdy "leciał" już inny wyjątek.
Innymi słowy, kod:
class A { public: ~A() { throw "aaa"; } }; void main() { try { A a; throw "bbb"; } catch(const char *s) { cout << "Exception " << s << endl; } }
skończy się SIGABORT'em i core, bo w czasie zwijania kontekstu po rzuceniu "bbb" z destruktora A poleci "aaa".
Sytuacji takich nie da się wykluczyć, jeśli pozwalamy na wyjątki rzucane z destruktorów. Po prostu: destruktor nigdy nie może rzucić wyjątku. Nie wolno mu. Może coś zalogować, ustawić jakieś flagi, zrobić cokolwiek - ale nie rzucać wyjątek.
Przy okazji: analogiczne objawy ma wystąpienie wyjątku, który nigdzie nie został złapany. W main-ie z zasady umieszczamy kod, który łapie wszelkie możliwe i niemożliwe typy wyjątków - ale gdy o tym zapomnimy, możemy nie skojarzyć tej najprostszej
możliwości.
komentarze obsługiwane przez Disqus