Özel durumlar ve hata işleme için modern C++ en iyi yöntemleri

Modern C++'da çoğu senaryoda hem mantıksal hataları hem de çalışma zamanı hatalarını raporlamanın ve işlemenin tercih edilen yolu özel durumları kullanmaktır. Bu durum özellikle yığının hatayı algılayan işlev ile hatayı işlemek için bağlamı olan işlev arasında birkaç işlev çağrısı içerebileceği durumlarda geçerlidir. Özel durumlar, bilgileri çağrı yığınına geçirmek üzere hataları algılayan kod için resmi, iyi tanımlanmış bir yol sağlar.

Olağanüstü kod için özel durumları kullanma

Program hataları genellikle iki kategoriye ayrılır:

  • Programlama hatalarının neden olduğu mantık hataları. Örneğin, "dizin aralık dışında" hatası.
  • Programcı denetimi dışında çalışma zamanı hataları. Örneğin, "ağ hizmeti kullanılamıyor" hatası.

C stili programlamada ve COM'da hata raporlama, hata kodunu temsil eden bir değer veya belirli bir işlev için durum kodu döndürülerek ya da hataların bildirilip bildirilmediğini görmek için her işlev çağrısından sonra çağıranın isteğe bağlı olarak alabileceği bir genel değişken ayarlanarak yönetilir. Örneğin, COM programlama çağırana HRESULT hataları iletmek için dönüş değerini kullanır. Ayrıca Win32 API'sinin GetLastError çağrı yığını tarafından bildirilen son hatayı alma işlevi vardır. Bu iki durumda da, kodu tanımak ve uygun şekilde yanıtlamak arayana bağlı olur. Çağıran hata kodunu açıkça işlemezse, program uyarı olmadan kilitlenebilir. Alternatif olarak, hatalı veriler kullanarak yürütmeye devam edebilir ve yanlış sonuçlar üretebilir.

Aşağıdaki nedenlerle modern C++ dilinde özel durumlar tercih edilir:

  • Özel durum, çağırma kodunu bir hata koşulunu tanımaya ve işlemeye zorlar. İşlenmeyen özel durumlar program yürütmeyi durdurur.
  • Bir özel durum, çağrı yığınında hatayı işleyebilen noktaya atlar. Ara işlevler özel durumun yayılmasına izin verebilir. Diğer katmanlarla eşgüdümlü olmaları gerekmez.
  • Özel durum yığınını geri alma mekanizması, iyi tanımlanmış kurallara göre bir özel durum oluşturulduktan sonra kapsamdaki tüm nesneleri yok eder.
  • Özel durum, hatayı algılayan kod ile hatayı işleyen kod arasında temiz bir ayrım sağlar.

Aşağıdaki basitleştirilmiş örnek, C++'da özel durumlar oluşturma ve yakalama için gerekli söz dizimini gösterir:

#include <stdexcept>
#include <limits>
#include <iostream>

using namespace std;

void MyFunc(int c)
{
    if (c > numeric_limits< char> ::max())
    {
        throw invalid_argument("MyFunc argument too large.");
    }
    //...
}

int main()
{
    try
    {
        MyFunc(256); //cause an exception to throw
    }

    catch (invalid_argument& e)
    {
        cerr << e.what() << endl;
        return -1;
    }
    //...
    return 0;
}

C++ içindeki özel durumlar C# ve Java gibi dillerdekilere benzer. Bloğundatry, bir özel durum oluşturulursa, türü özel durumla eşleşen ilk ilişkili catch blok tarafından yakalanılır. Başka bir deyişle, yürütme deyiminden throw deyimine catch atlar. Kullanılabilir bir yakalama bloğu bulunmazsa çağrılır std::terminate ve programdan çıkar. C++'ta herhangi bir tür oluşturulabilir; ancak, doğrudan veya dolaylı olarak öğesinden std::exceptiontüretilen bir tür oluşturmanızı öneririz. Önceki örnekte, özel durum türü, invalid_argumentüst bilgi dosyasındaki standart kitaplıkta <stdexcept> tanımlanmıştır. C++ bir özel durum oluştuğunda tüm kaynakların serbest bırakıldığından emin olmak için bir finally blok sağlamaz veya gerektirmez. Kaynak alımı, akıllı işaretçiler kullanan başlatma (RAII) deyimi, kaynak temizleme için gerekli işlevselliği sağlar. Daha fazla bilgi için bkz . Nasıl yapılır: Özel durum güvenliği için tasarım. C++ yığın geri sarma mekanizması hakkında bilgi için bkz . Özel durumlar ve yığın geri sarmayı kaldırma.

Temel yönergeler

Tüm programlama dillerinde güçlü hata işleme zorlayıcıdır. Özel durumlar, iyi hata işlemeyi destekleyen çeşitli özellikler sağlasa da, tüm işleri sizin için yapamazlar. Özel durum mekanizmasının avantajlarını gerçekleştirmek için kodunuzu tasarlarken özel durumları göz önünde bulundurun.

  • Her zaman doğru veya her zaman yanlış olması gereken koşulları denetlemek için onayları kullanın. Genel işlevlerin parametrelerinde giriş doğrulama hataları gibi oluşabilecek hataları denetlemek için özel durumları kullanın. Daha fazla bilgi için Özel durumlar ve onaylar bölümüne bakın.
  • Hatayı işleyen kod bir veya daha fazla araya gelen işlev çağrısı tarafından hatayı algılayan koddan ayrıldığında özel durumları kullanın. Hatayı işleyen kod, bunu algılayan kodla sıkı bir şekilde birleştirildiğinde performans açısından kritik döngülerde bunun yerine hata kodlarının kullanılıp kullanılmayacağını göz önünde bulundurun.
  • Özel durum oluşturabilecek veya yayabilecek her işlev için üç özel durum garantilerinden birini sağlayın: güçlü garanti, temel garanti veya nothrow (noexcept) garantisi. Daha fazla bilgi için bkz . Nasıl yapılır: Özel durum güvenliği için tasarım.
  • Değere göre özel durumlar oluşturun, başvuruya göre yakalayın. Üstesinden gelemediklerine yakalanma.
  • C++11'de kullanım dışı bırakılan özel durum belirtimlerini kullanmayın. Daha fazla bilgi için Özel durum belirtimleri ve noexcept bölümüne bakın.
  • Standart kitaplık özel durum türlerini uygulandığında kullanın. Sınıf hiyerarşisinden exception özel özel durum türleri türet.
  • Özel durumların yıkıcılardan veya bellek serbest bırakma işlevlerinden kaçmasına izin verme.

Özel durumlar ve performans

Özel durum mekanizması, özel durum oluşturmazsa en düşük performans maliyetine sahiptir. Bir özel durum oluşursa, yığın geçişi ve geri sarmanın maliyeti kabaca bir işlev çağrısının maliyetiyle karşılaştırılabilir. Bir try blok girildikten sonra çağrı yığınını izlemek için diğer veri yapıları ve özel durum oluşursa yığının geri alınması için daha fazla yönerge gerekir. Ancak çoğu senaryoda performans ve bellek ayak izi maliyeti önemli değildir. Özel durumların performans üzerindeki olumsuz etkisi büyük olasılıkla yalnızca bellek kısıtlanmış sistemler üzerinde önemli olacaktır. Ya da performans açısından kritik döngülerde, bir hatanın düzenli olarak oluşma olasılığı yüksektir ve bunu işlemek için kod ile bunu bildiren kod arasında sıkı bir bağlantı vardır. Her durumda, profil oluşturmadan ve ölçmeden özel durumların gerçek maliyetini bilmek mümkün değildir. Maliyetin önemli olduğu nadir durumlarda bile, iyi tasarlanmış bir özel durum ilkesi tarafından sağlanan artan doğruluk, daha kolay bakım ve diğer avantajlara karşı tartabilirsiniz.

Özel durumlar ve onaylar karşılaştırması

Özel durumlar ve onaylar, bir programdaki çalışma zamanı hatalarını algılamaya yönelik iki ayrı mekanizmadır. Geliştirme sırasında her zaman doğru veya tüm kodunuz doğruysa her zaman yanlış olması gereken koşulları test etmek için deyimleri kullanın assert . Hata, koddaki bir şeyin düzeltilmesi gerektiğini gösterdiğinden, özel durum kullanarak böyle bir hatayı işlemenin bir anlamı yoktur. Programın çalışma zamanında kurtarılması gereken bir koşulu temsil etmez. , assert hata ayıklayıcıda program durumunu inceleyebilmeniz için deyiminde yürütmeyi durdurur. Bir özel durum, ilk uygun catch işleyicisinden yürütmeye devam eder. Kodunuz doğru olsa bile çalışma zamanında oluşabilecek hata koşullarını denetlemek için özel durumları kullanın( örneğin, "dosya bulunamadı" veya "bellek yetersiz." Kurtarma yalnızca bir günlüğe ileti alıp programı sonlandırsa bile özel durumlar bu koşulları işleyebilir. Özel durumları kullanarak bağımsız değişkenleri her zaman genel işlevlere denetleyin. İşleviniz hatasız olsa bile, kullanıcının iletebileceği bağımsız değişkenler üzerinde tam denetime sahip olmayabilirsiniz.

C++ özel durumları ve Windows SEH özel durumları

Hem C hem de C++ programları Windows işletim sistemindeki yapılandırılmış özel durum işleme (SEH) mekanizmasını kullanabilir. SEH'deki kavramlar, SEH'nin ve yerine , __exceptve __finally yapılarını kullanması __trydışında C++ özel durumlarındakine catchbenzer.try Microsoft C++ derleyicisinde (MSVC), SEH için C++ özel durumları uygulanır. Ancak, C++ kodu yazarken C++ özel durum söz dizimini kullanın.

SEH hakkında daha fazla bilgi için bkz . Yapılandırılmış Özel Durum İşleme (C/C++).

Özel durum belirtimleri ve noexcept

Bir işlevin oluşturabileceği özel durumları belirtmenin bir yolu olarak C++ ile özel durum belirtimleri kullanıma sunulmuştur. Ancak, özel durum belirtimleri uygulamada sorunlu olduğunu kanıtladı ve C++11 taslak standardında kullanım dışı bırakıldı. dışında, işlevinin kaçış için özel durumlara izin vermediğini gösteren özel durum belirtimlerini throw()kullanmamanızı throw öneririz. Kullanım dışı bırakılan formun throw( type-name )özel durum belirtimlerini kullanmanız gerekiyorsa, MSVC desteği sınırlıdır. Daha fazla bilgi için bkz . Özel Durum Belirtimleri (throw). Tanımlayıcı noexcept , C++11'de tercih edilen alternatif olarak kullanıma sunulmuştur throw().

Ayrıca bkz.

Nasıl yapılır: Olağanüstü ve istisnai olmayan kodlar arasındaki arabirim
C++ dil başvurusu
C++ Standart Kitaplığı