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