Bezpečnost výjimek je stav, kdy kód funguje správně i v případě vyvolání výjimky. Aby se zajistila bezpečnost výjimek, vyvinuli tvůrci standardní knihovny jazyka C++ sadu úrovní bezpečnosti výjimek, což jsou smluvní záruky chování operací datové struktury s ohledem na výjimky. Implementátoři knihovny i klienti mohou tyto záruky využít při posuzování správnosti zpracování výjimek. Úrovně bezpečnosti výjimek platí stejně i pro jiné jazyky a mechanismy zpracování chyb.

Historie Jak píše David Abrahams „Než se v jazyce C++ objevily výjimky, nikdo o ‚bezpečnosti proti chybám‘ nemluvil.“ Tento pojem se objevil v publikacích výboru JTC1/SC22/WG21 pro standard C++ již v roce 1994. Bezpečnost výjimek pro standardní knihovnu C++ byla poprvé formalizována pro STLport Abrahamsem, který zavedl rozlišení mezi základní bezpečností a silnou bezpečností. V pozdějším návrhu bylo toto rozlišení rozšířeno na moderní záruky stupně základní/silná/bez výjimek ().

Souvislosti Výjimky představují druh nelokální řídicí struktury, u níž může výjimka „vypadnout“ z volané funkce. Vypadnutí může následujícím způsobem způsobit chybu v bezpečnosti výjimek porušením invariantů modifikovatelné datové struktury:

Provedení operace na modifikovatelné datové struktuře modifikuje data a poruší invariant. Je vyvolána výjimka a řízení se „přenese“ nahoru, čímž se přeskočí zbývající část kódu operace, která by invariant obnovila. Výjimka je zachycena a je provedeno zotavení, nebo je spuštěn blok finally. Datová struktura s porušeným invariantem je použita kódem, který tento invariant předpokládá, což vede k chybě.

O kódu s takovou chybou, jaká je popsána výše, říkáme, že je „výjimkově nebezpečný“.

Klasifikace Standardní knihovna C++ poskytuje několik úrovní bezpečnosti výjimek (zde uvedených od nejbezpečnější): Záruka nevyvolání výjimky () neboli transparentnost selhání (): Je zaručeno, že operace budou úspěšné a splní všechny požadavky i ve výjimečných situacích. Pokud dojde k výjimce, bude ošetřena interně a klienti ji nezaznamenají. Silná bezpečnost výjimek (), neboli sémantika potvrzení/vrácení (): Operace může selhat, ale při selhání je zaručeno, že nebudou mít žádné postranní efekty, takže původní hodnoty budou zachovány. Základní bezpečnost výjimek (): Částečné provedení operace může způsobit postranní efekty, ale nedojde k porušení invariantů. Veškerá uložená data budou obsahovat platné hodnoty, které se mohou lišit od původních hodnot. Únik prostředků (případně jejich vyčerpání, včetně vyčerpání paměti) jsou obvykle vyloučeny invariantem, který stanovuje, že všechny prostředky jsou evidovány a spravovány. Žádná bezpečnost výjimek: Zcela bez záruky bezpečnosti.

Pro robustní kód je obvykle vyžadována alespoň základní bezpečnost výjimek. Vyšší úrovně bezpečnosti mohou být někdy obtížně dosažitelné, a mohou způsobovat režijní náklady kvůli dodatečnému kopírování. Klíčovým mechanismem pro bezpečnost výjimek je klauzule finally nebo podobná syntaxe zpracování výjimek, která zajišťuje, že při opuštění bloku se vždy spustí určitý kód, i když došlo k výjimce. Některé jazyky mají konstrukce, které to zjednodušují, především pomocí vzoru dispose, který je v C# realizován pomocí using, v Pythonu with a v Javě) try-s-prostředky.

Příklad Uvažujme typ chytrého vektoru, jako je std::vector<T> v C++ nebo java.util.ArrayList<T> v Javě. Pokud se přidává položka x k vektoru v, musí vektor skutečně přidat x k vnitřnímu seznamu objektů a aktualizovat položku, která udává, kolik objektů je ve v. Možná bude potřeba také alokovat paměť, pokud existující kapacita není dostačující.

Alternativy bezpečnosti výjimek: Záruka nevyvolání výjimky: Implementováno zajištěním, že přidělování paměti nikdy neselže nebo definováním chování funkce insert() při selhání přidělení paměti (například tím, že funkce bude vracet hodnotu typu boolean udávající zda přidělení paměti uspělo). Silná bezpečnost výjimek: Implementováno provedením všech přidělení paměti napřed, a následným prohozením bufferů, pokud nedošlo k chybě (tzv. idiom copy-and-swap). V tomto případě buď přidání x do v uspěje nebo v zůstane nezměněné bez ohledu na selhání při alokaci paměti. Základní bezpečnost výjimek: Implementováno zajištěním, že položka udávající počet prvků bude zaručeně obsahovat výslednou velikost pole v. Pokud například dojde k chybě, funkce insert() úplně uvolní v a vynuluje počet jeho prvků. Při selhání nedojde k úniku žádného prostředku, ale původní hodnota v není zachována. Žádná bezpečnost výjimek: Selhání při alokaci může způsobit poškození obsahu v, nesprávný údaj o počtu prvků nebo únik prostředků.

Odkazy

Reference

Externí odkazy

Kategorie:C++ Kategorie:Řízení běhu