C++'da istisna sistemi, try-catch mekanizmasına ve throw anahtar kelimesine dayanmaktadır. İstisnai bir durum (örneğin, kaynak hatası, invariant ihlali) meydana geldiğinde, try bloğu içinde istisna throw operatörü ile başlatılır (fırlatılır). Uygun işleyiciyi bulma işlemi (catch) yığının üstünden ilk eşleşen tür bulunana kadar devam eder.
Önemli detaylar:
std::exception sınıfından türetilmiş bir sınıf).noexcept belirticisi getirilmiştir.Tasarım:
catch(const std::exception& e).Kod örneği:
#include <iostream> #include <stdexcept> void mayFail(bool fail) { if (fail) throw std::runtime_error("İşlem hatası"); } int main() { try { mayFail(true); } catch (const std::exception& ex) { std::cout << "Yakalanan istisna: " << ex.what() << std::endl; } }
Eğer bir istisna, başka bir istisna yukarı doğru iletilirken yok ediciden fırlatılırsa ne olacaktır?
Cevap: Program std::terminate() ile aniden sonlanır, çünkü istisna işlenirken yeni bir istisna (double exception) fırlatılmasına izin verilmez, aksi halde yığın açılımı bozulur.
Örnek:
struct CrashOnDestruct { ~CrashOnDestruct() noexcept(false) { throw std::runtime_error("Yok edicide hata!"); } }; void func() { CrashOnDestruct obj; throw std::logic_error("Hata işleme"); } int main() { try { func(); } catch (...) { } } // std::terminate() ile sonlanır
Hikaye
Büyük bir finansal uygulamada istisnalar, bir veritabanı sarmalayıcı sınıfının yok edicisinden fırlatılıyordu. Hata meydana geldiğinde ana işlemlerden biri bir istisna başlatıyordu, unwind çıkışında yok edici çağrılıyordu ve o da hata fırlatıyordu. Tüm uygulama, kullanıcıların işlerini kaybetmesiyle aniden sonlanıyordu. Geliştiricilerin, yok edicilerde
throwyerine log kaydı ve düzgün işleme geçirmesi gerekiyordu.
Hikaye
Mikro hizmet, istisnaları türüne göre işliyordu: catch(std::exception). Bir iş parçacığı, kullanıcı türünde istisnalar fırlatıyordu (std::exception'dan türemiyordu). Bu tür hatalar yakalanmadı ve beklenmedik bir bağlantı kopması ile bellek sızıntısına neden oldu.
Hikaye
Konteynerlerin taşıma yöntemlerinde noexcept spesifikatorünün eksikliği, standart kütüphanenin hızlı hareket kopyası yerine yavaş kopyalamayı kullanmasıyla sonuçlandı; önemli bir performans kaybı sadece yük testlerinde ortaya çıkarıldı.