Ana Sayfa

C++ İstisnaları ve Yapısal İstisnalar: Gizli Bir Tuzak

1 dk okuma

Bir müşteri, C++ projelerinde yapısal istisnaları (structured exceptions - SEH) C++ istisnaları olarak yakalamak istiyordu, ancak bunu /EHa derleyici anahtarını kullanmadan yapmayı hedefliyordu. /EHa anahtarı, hem eşzamansız (yapısal) hem de eşzamanlı (C++) istisnaları yakalayan bir istisna işleme modeli sunsa da, derleyici optimizasyonlarını önemli ölçüde engellediği ve daha büyük kod boyutuna yol açtığı biliniyordu. Müşterinin "şeytani" planı, işlenmemiş bir istisna filtresi (unhandled exception filter) kurarak yapısal istisnaları yakalamak ve bunları bir C++ istisnasına dönüştürerek yeniden atmaktı. Bu sayede, bir erişim ihlali (access violation) gibi yapısal bir hata, standart bir C++ istisnası olarak ele alınabilecek ve /EHa seçeneğinin getirdiği performans cezalarından kaçınılacaktı.

Ancak, bu "akıllıca" görünen çözüm her zaman beklendiği gibi çalışmadı. Makalede verilen örnekte, printf fonksiyonunun bulunduğu bir try-catch bloğu içinde yapısal bir istisna C++ istisnasına dönüştürüldüğünde yakalanabiliyordu. Ancak printf çağrısı kaldırıldığında, aynı istisna yakalanamıyordu. Bunun nedeni, derleyicinin printf gibi noexcept olarak işaretlenmemiş bir fonksiyonun C++ istisnası atabileceği ihtimalini göz önünde bulundurmasıdır. Bu durum, derleyicinin try bloğunu aktif tutmasını sağlar. printf kaldırıldığında ise derleyici, try bloğunun içindeki kodun C++ istisnası atma potansiyelini görmediği için optimizasyonlar yapar ve try bloğunun istisna yakalama mekanizmasını devre dışı bırakabilir.

Temel sorun, try bloğunun, CleverConversion gibi istisna filtrelerinin attığı istisnaları yakalamak için değil, kendi içindeki koddan kaynaklanan C++ istisnalarını yakalamak için tasarlanmış olmasıdır. Yapısal istisna, try bloğunun kapsamı dışında meydana gelir ve filtre tarafından C++ istisnasına dönüştürülüp atıldığında, bu yeni C++ istisnası için aktif bir try bloğu bulunmayabilir. Bu durum, istisna işleme modellerinin karmaşıklığını ve derleyici optimizasyonlarının beklenmedik yan etkilerini gözler önüne serer. Güvenilir istisna yönetimi için derleyicinin sunduğu standart mekanizmaların kullanılması gerektiği vurgulanmaktadır.

İçgörü

C++ istisnalarını yapısal istisnalardan dönüştürme girişimleri, derleyici optimizasyonları ve istisna işleme modellerinin karmaşıklığı nedeniyle beklenmedik ve güvenilmez sonuçlar doğurabilir.

Kaynak