exception safety
Főnév
exception safety (tsz. exception safeties)
- (informatika) Kivételbiztonság azt jelenti, hogy a program egy kivétel dobása után is konzisztens állapotban marad. A C++ nyelv lehetővé teszi, hogy hibakezelésre
try–catchblokkokkal ésthrowutasítással kivételeket használjunk – ezek megzavarhatják a normál vezérlésmenetet. Az exception safety garantálja, hogy a kivételek ellenére ne szivárogjon memória, ne romoljon el az objektum állapota, és a program biztonságosan folytatható vagy lezárható legyen.
🛡️ A kivételbiztonság szintjei (Herb Sutter szerint)
C++-ban négy klasszikus szintet különböztetünk meg:
✅ 1. No-throw guarantee (erős garancia)
A művelet garantáltan nem dob kivételt.
- Erre példa lehet destruktorok vagy
swap()függvények megvalósítása. - Használat: konténerek,
std::vector::resize,std::unique_ptr
void biztonsagos() noexcept {
// semmi nem dobhat
}
Az noexcept kulcsszó C++11-től garantálja ezt.
🔄 2. Strong guarantee (visszavonhatóság)
Ha kivétel történik, az objektum eredeti állapota megmarad.
- A művelet vagy teljesen sikerül, vagy nem változik semmi.
- Ez gyakran jelentős többletmunkát jelent, pl. ideiglenes objektumok használatával.
Példa:
std::vector<int> v = {1, 2, 3};
try {
v.insert(v.begin(), 42); // ha nem sikerül, v változatlan marad
} catch (...) {
// v nem sérült
}
🔁 3. Basic guarantee (minimális biztonság)
A művelet után az objektum érvényes, de az állapota megváltozhat.
- Nem történik memória- vagy erőforrásszivárgás.
- A program stabil, de az eredmények nem mindig garantáltak.
Példa:
void push(int x) {
data.push_back(x); // ha dob kivételt, az objektum akkor is használható
}
❌ 4. No guarantee (nincs garancia)
Kivétel esetén az objektum érvénytelen állapotba kerülhet.
- Ez kerülendő.
- Csak akkor elfogadható, ha nem lehet másképp megoldani, és dokumentálva van.
🧠 Miért fontos?
- Stabil programozás: A kivételbiztos kód nem omlik össze váratlanul.
- Erőforráskezelés: Megakadályozható memória, fájl, mutex szivárgás.
- Karbantarthatóság: Az ilyen kód könnyebben debugolható és bővíthető.
- Standard könyvtár: A C++ STL osztályai nagy részben kivételbiztosak.
📦 Példa: nem biztonságos kód
void nemBiztonsagos(std::vector<int>& v) {
v.push_back(10); // lehet kivétel: memória!
v[0] = 999; // csak akkor hajtódik végre, ha nem volt kivétel
}
Ha push_back() kivételt dob, v[0] = 999 már nem fut le → az állapot félbemaradt lehet.
🔄 Megoldás: strong guarantee RAII-vel
void biztonsagos(std::vector<int>& v) {
std::vector<int> temp = v;
temp.push_back(10); // ha ez elbukik, v változatlan
temp[0] = 999;
v.swap(temp);
}
🧰 Eszközök a kivételbiztonsághoz
RAII (Resource Acquisition Is Initialization)
- Az erőforrásokat (memória, fájl) olyan objektumhoz rendeljük, ami destruktorban felszabadítja azokat.
- Ha kivétel történik, a destruktor automatikusan fut le → nincs szivárgás.
std::unique_ptr<int> ptr(new int(42)); // automatikus felszabadítás
Smart pointerek
std::unique_ptr,std::shared_ptrkivételbiztonságot adnak.- Automatikusan elvégzik a
delete-et, akkor is, ha kivétel történik.
noexcept kulcsszó (C++11+)
Azt jelzi a fordítónak és programozóknak, hogy egy függvény nem dob kivételt.
void torol() noexcept; // garantáltan nem dob kivételt
A std::swap, move műveletek noexcept-ként működnek hatékonyan, különben a konténerek például másolni fognak move helyett.
🧪 STL példák
std::vector::push_back
- Ha új tárhely kell → memóriaallokáció → kivételt dobhat → basic guarantee
std::vector::resize
- Ha
Tkonstruktor kivételmentes → strong guarantee
🔄 Operátorok és kivételbiztonság
Az operátorokat, mint operator=, operator+, érdemes kivételbiztosan implementálni:
MyClass& operator=(const MyClass& other) {
if (this != &other) {
MyClass temp(other);
swap(temp); // strong guarantee
}
return *this;
}
📋 Tippek a kivételbiztos kódhoz
| Tipp | Miért hasznos |
|---|---|
Használj try/catch-et csak magas szinten |
Ne tömd tele kivételkezeléssel a kis függvényeket |
| RAII mindenre | Erőforrás- és állapotkezelés automatikusan |
| Kerüld a kivételeket destruktorban | Előfordulhat, hogy másik kivétel már aktív |
Preferáld noexcept-et |
Gyorsabb és megbízhatóbb |
| Használj másolás/move-and-swap idiomát | Erős garanciához kiváló |
❓ Mi történik, ha kivétel van a destruktorban?
Kritikus helyzet!
Ha egy kivétel történik egy másik kivétel közben (pl. destruktorban), a program terminate()-et hív → leállás.
Ezért:
~MyClass() noexcept {
try {
// műveletek
} catch (...) {
// csendben elnyeli a hibát
}
}
🔚 Összefoglalás
| Fogalom | Leírás |
|---|---|
| Exception safety | Biztonságos viselkedés kivételek esetén |
| No-throw | Semmilyen kivételt nem dob |
| Strong | Vagy sikerül, vagy nem változik semmi |
| Basic | Érvényes, de módosulhat az állapot |
| No guarantee | Semmit nem garantál |
| Eszközök | RAII, smart pointer, swap idiom, noexcept |
| STL viselkedés | Jellemzően legalább basic guarantee |
💬 Zárógondolat
A kivételbiztonság nemcsak „extra védelem”, hanem alapfeltétele a megbízható programoknak. A modern C++ lehetővé teszi, hogy erős garanciákat adjunk, és a helyes erőforrás-kezeléssel és noexcept-tel stabil és hatékony kódot írjunk – még akkor is, ha a dolgok félremennek.
- exception safety - Szótár.net (en-hu)
- exception safety - Sztaki (en-hu)
- exception safety - Merriam–Webster
- exception safety - Cambridge
- exception safety - WordNet
- exception safety - Яндекс (en-ru)
- exception safety - Google (en-hu)
- exception safety - Wikidata
- exception safety - Wikipédia (angol)