Aracılığıyla paylaş


C/C++ Onaylamaları

Onay deyimi, programınızın bir noktasında doğru olmasını beklediğiniz bir koşulu belirtir. Bu koşul doğru değilse onay başarısız olur, programınızın yürütülmesi kesilir ve Onay Başarısız iletişim kutusu görüntülenir.

Visual Studio, aşağıdaki yapıları temel alan C++ onay deyimlerini destekler:

  • MFC programları için MFC doğrulamaları.

  • ATL kullanan programlar için ATLASSERT.

  • C çalışma zamanı kitaplığını kullanan programlar için CRT varsayımları.

  • Diğer C/C++ programları için ANSI onay işlevi .

    Onayları kullanarak mantıksal hataları yakalayabilir, bir işlemin sonuçlarını denetleyebilir ve işlenmesi gereken hata koşullarını test edebilirsiniz.

Bu konuda,

Onaylar nasıl çalışır?

Hata Ayıklama ve Yayın derlemelerindeki doğrulamalar

Onayları kullanmanın yan etkileri

CRT doğrulamaları

MFC onayları

Onaylar nasıl çalışır?

Bir MFC veya C çalışma zamanı kitaplığı onayı nedeniyle hata ayıklayıcı durdurulduğunda, kaynak kullanılabilir durumdaysa, hata ayıklayıcı onay işleminin gerçekleştiği kaynak dosyadaki noktaya gider. Onay iletisi hem Çıktı penceresinde hem de Onay Başarısız iletişim kutusunda görünür. İleride başvurmak üzere kaydetmek istiyorsanız onay iletisini Çıkış penceresinden bir metin penceresine kopyalayabilirsiniz. Çıkış penceresi başka hata iletileri de içerebilir. Onay hatasının nedeni hakkında ipuçları sağladığından bu iletileri dikkatle inceleyin.

Geliştirme sırasında hataları algılamak için onayları kullanın. Kural olarak, her varsayım için bir onay kullanın. Örneğin, bağımsız değişkenin NULL olmadığını varsayarsanız, bu varsayımı test etmek için bir assert kullanın.

Bu konuda

Hata Ayıklama ve Sürüm derlemelerindeki Onaylar

Onay ifadeleri yalnızca _DEBUG tanımlıysa derlenir. Aksi takdirde, derleyici onayları boş ifadeler olarak kabul eder. Bu nedenle, doğrulama ifadeleri, son Sürüm programınızda ek yük veya performans maliyeti getirmez ve #ifdef direktiflerini kullanmaktan kaçınmanıza olanak tanır.

Doğrulama kullanmanın yan etkileri

Kodunuza onaylar eklediğinizde onayların yan etkileri olmadığından emin olun. Örneğin, nM değerini değiştiren aşağıdaki assertion (doğrulama) işlemini göz önünde bulundurun:

ASSERT(nM++ > 0); // Don't do this!

ASSERT İfade, programınızın Yayın sürümünde değerlendirilmediğinden, nM Hata Ayıklama ve Sürüm sürümlerinde farklı değerlere sahip olur. MFC'de bu sorunu önlemek için yerine VERIFY makrosunu ASSERTkullanabilirsiniz. VERIFY ifadeyi tüm sürümlerde değerlendirir ancak Sürüm sürümündeki sonucu denetlemez.

Bir işlevi değerlendirmenin beklenmeyen yan etkileri olabileceği için, onay deyimlerinde işlev çağrılarını kullanma konusunda özellikle dikkatli olun.

ASSERT ( myFnctn(0)==1 ) // unsafe if myFnctn has side effects
VERIFY ( myFnctn(0)==1 ) // safe

VERIFY, hem Hata Ayıklama hem de Yayın sürümlerinde myFnctn çağırır, bu nedenle kullanılması kabul edilebilir. Ancak, VERIFY kullanmak Yayın sürümünde gereksiz bir işlev çağrısının yükünü getirir.

Bu başlıkta

CRT doğrulamaları

Üst CRTDBG.H bilgi dosyası onay denetimi için ve _ASSERT makrolarını tanımlar_ASSERTE.

Macro Result
_ASSERT Belirtilen ifade YANLIŞ olarak değerlendirilirse, dosya adı ve satır numarası _ASSERT olacaktır.
_ASSERTE ile aynı, _ASSERTayrıca onaylanan ifadenin dize gösterimi.

_ASSERTE daha güçlüdür çünkü YANLIŞ olduğu ortaya çıkan onaylanan ifadeyi bildirir. Bu, kaynak koda başvurmadan sorunu tanımlamak için yeterli olabilir. Ancak, uygulamanızın Hata Ayıklama sürümü, _ASSERTE tarafından onaylanan her bir ifade için bir dize sabiti içerir. Çok sayıda _ASSERTE makro kullanıyorsanız, bu dize ifadeleri önemli miktarda bellek alır. Bunun bir sorun olduğu kanıtlanırsa, belleği kaydetmek için kullanın _ASSERT .

_DEBUG tanımlandığında, _ASSERTE makro aşağıdaki gibi tanımlanır:

#define _ASSERTE(expr) \
    do { \
        if (!(expr) && (1 == _CrtDbgReport( \
            _CRT_ASSERT, __FILE__, __LINE__, #expr))) \
            _CrtDbgBreak(); \
    } while (0)

Onaylanan ifade YANLIŞ olarak değerlendirilirse, doğrulama başarısızlığını bildirmek için _CrtDbgReport çağrılır (varsayılan olarak bir ileti iletişim kutusu ile). İleti iletişim kutusunda Yeniden Dene'yi seçerseniz, _CrtDbgReport 1 döndürür ve _CrtDbgBreak aracılığıyla DebugBreakhata ayıklayıcısını çağırır.

Geçici olarak tüm onaylama ifadelerini devre dışı bırakmanız gerekiyorsa _CtrSetReportMode kullanın.

Yığın Bozulması Kontrol Ediliyor

Aşağıdaki örnek, yığının bozulmasını denetlemek için _CrtCheckMemory kullanır:

_ASSERTE(_CrtCheckMemory());

İşaretçi Geçerliliğini Denetleme

Aşağıdaki örnek, belirli bir bellek aralığının okuma veya yazma için geçerli olduğunu doğrulamak için _CrtIsValidPointer kullanır.

_ASSERTE(_CrtIsValidPointer( address, size, TRUE );

Aşağıdaki örnek, bir işaretçinin yerel yığındaki belleğe işaret ettiğini doğrulamak için _CrtIsValidHeapPointer kullanır (C çalışma zamanı kitaplığının bu örneği tarafından oluşturulan ve yönetilen yığın - bir DLL, kitaplığın kendine özgü bir örneğine ve dolayısıyla uygulama yığını dışında kendi yığınına sahip olabilir). Bu kontrol yalnızca null veya sınır dışı adresleri değil, aynı zamanda statik değişkenlere, yığın değişkenlerine ve diğer yerel olmayan belleğe yönelik işaretçileri de yakalar.

_ASSERTE(_CrtIsValidHeapPointer( myData );

Bellek Bloğunu Denetleme

Aşağıdaki örnek, bir bellek bloğunun yerel yığında olduğunu ve geçerli bir blok türüne sahip olduğunu doğrulamak için _CrtIsMemoryBlock kullanır.

_ASSERTE(_CrtIsMemoryBlock (myData, size, &requestNumber, &filename, &linenumber));

Bu başlıkta

MFC onayları

MFC, onay denetimi için ASSERT makrosunu tanımlar. Ayrıca, MFC ASSERT_VALID ve CObject::AssertValid yöntemlerini, türetilmiş bir CObject nesnenin iç durumunu denetlemek için tanımlar.

MFC ASSERT makrosunun bağımsız değişkeni sıfır veya yanlış olarak değerlendirilirse, makro program yürütmesini durdurur ve kullanıcıyı uyarır; aksi takdirde yürütme devam eder.

Onay başarısız olduğunda, bir ileti iletişim kutusu kaynak dosyanın adını ve onayın satır numarasını gösterir. İletişim kutusunda 'Yeniden Dene'yi seçerseniz, AfxDebugBreak çağrısı, yürütmenin hata ayıklayıcıda kesilmesine neden olur. Bu noktada çağrı yığınını inceleyebilir ve onaylama işleminin neden başarısız olduğunu belirlemek için diğer hata ayıklayıcı olanaklarını kullanabilirsiniz. Tam zamanında hata ayıklamayı etkinleştirdiyseniz ve hata ayıklayıcı zaten çalışmıyorsa, iletişim kutusu hata ayıklayıcıyı başlatabilir.

Aşağıdaki örnekte bir işlevin dönüş değerini denetlemek için nasıl kullanılacağı ASSERT gösterilmektedir:

int x = SomeFunc(y);
ASSERT(x >= 0);   //  Assertion fails if x is negative

İşlev bağımsız değişkenlerinin tür denetimini sağlamak için ASSERT işlevini IsKindOf işleviyle kullanabilirsiniz:

ASSERT( pObject1->IsKindOf( RUNTIME_CLASS( CPerson ) ) );

Makro, ASSERT Yayın sürümünde kod üretmez. Release sürümünde ifadeyi değerlendirmeniz gerekiyorsa ASSERT yerine VERIFY makrosunu kullanın.

MFC ASSERT_VALID ve CObject::AssertValid

CObject::AssertValid yöntemi, bir nesnenin iç durumunun çalışma zamanı denetimlerini sağlar. Sınıfınızı CObject'den türetirken AssertValid öğesini geçersiz kılmanız gerekmese de, bunu yaparak sınıfınızı daha güvenilir hale getirebilirsiniz. AssertValid geçerli değerler içerdiğini doğrulamak için nesnenin tüm üye değişkenlerinde onaylar gerçekleştirmelidir. Örneğin, işaretçi üye değişkenlerinin NULL olmadığını denetlemelidir.

Aşağıdaki örnekte bir AssertValid işlevin nasıl bildirileceği gösterilmektedir.

class CPerson : public CObject
{
protected:
    CString m_strName;
    float   m_salary;
public:
#ifdef _DEBUG
    // Override
    virtual void AssertValid() const;
#endif
    // ...
};

geçersiz kıldığınızda AssertValid, kendi denetimlerinizi gerçekleştirmeden önce temel sınıf sürümünü AssertValid çağırın. Ardından, burada gösterildiği gibi türetilmiş sınıfınıza özgü üyeleri denetlemek için ASSERT makrosunu kullanın:

#ifdef _DEBUG
void CPerson::AssertValid() const
{
    // Call inherited AssertValid first.
    CObject::AssertValid();

    // Check CPerson members...
    // Must have a name.
    ASSERT( !m_strName.IsEmpty());
    // Must have an income.
    ASSERT( m_salary > 0 );
}
#endif

Üye değişkenlerinizden herhangi biri nesne depoluyorsa, sınıfları AssertValid tarafından geçersiz kılınmışsa, iç geçerliliklerini ASSERT_VALID makrosunu kullanarak test edebilirsiniz.

Örneğin, bir CMyData öğesini üye değişkenlerinden birinde depolayan bir sınıfını göz önünde bulundurun. CObList değişkeni bir m_DataListnesne koleksiyonu CPerson depolar. Kısaltılmış bildirimi CMyData şöyle görünür:

class CMyData : public CObject
{
    // Constructor and other members ...
    protected:
        CObList* m_pDataList;
    // Other declarations ...
    public:
#ifdef _DEBUG
        // Override:
        virtual void AssertValid( ) const;
#endif
    // And so on ...
};

AssertValid'deki CMyData geçersiz kılma şu şekilde görünür:

#ifdef _DEBUG
void CMyData::AssertValid( ) const
{
    // Call inherited AssertValid.
    CObject::AssertValid( );
    // Check validity of CMyData members.
    ASSERT_VALID( m_pDataList );
    // ...
}
#endif

CMyData AssertValid, veri üyesinde depolanan nesnelerin geçerliliğini test etmek için mekanizmasını kullanır. geçersiz kılma AssertValid , CMyData makroyu ASSERT_VALID kendi m_pDataList üye değişkeni için çağırır.

Geçerlilik testi bu düzeyde durmuyor çünkü sınıf CObList ayrıca AssertValid'yi de geçersiz kılar. Bu geçersiz kılma, listenin iç durumunun geçerliliğini ek olarak test eder. Bu nedenle, bir CMyData nesnedeki geçerlilik testi, depolanan CObList liste nesnesinin iç durumları için ek geçerlilik testlerine yol açar.

Daha fazla çalışmayla, listede depolanan nesneler için CPerson de geçerlilik testleri ekleyebilirsiniz. CObList öğesinden bir sınıf CPersonList türetebilir ve AssertValid geçersiz kılabilirsiniz. Geçersiz kılmada, CObject::AssertValid çağırdıktan sonra, listeyi yineleyip listede depolanan her CPerson nesnesi üzerinde AssertValid çağırırsınız. Bu konunun başında gösterilen CPerson sınıfı, zaten AssertValid geçersiz kılar.

Bu, hata ayıklama için derleme yaparken güçlü bir mekanizmadır. Daha sonra yayın için derleme yaptığınızda mekanizma otomatik olarak kapatılır.

AssertValid sınırlamaları

Tetiklenen onay, nesnenin kesinlikle kötü olduğunu ve yürütmenin durdurulacağını gösterir. Ancak, onay eksikliği yalnızca hiçbir sorun bulunmadığını gösterir, ancak nesnenin iyi olması garanti değildir.

Bu başlıkta

Doğrulama kullanma

Mantıksal hataları yakalama

Programınızın mantığına göre doğru olması gereken bir koşulda doğrulama ayarlayabilirsiniz. Bir mantıksal hata oluşmadığı sürece onaylama işleminin hiçbir etkisi yoktur.

Örneğin, bir kapsayıcıda gaz moleküllerini simüle ettiğinizi ve değişkenin numMols toplam molekül sayısını temsil ettiğinizi varsayalım. Bu sayı sıfırdan küçük olamaz, bu nedenle aşağıdaki gibi bir MFC onay deyimi ekleyebilirsiniz:

ASSERT(numMols >= 0);

Bu şekilde bir CRT doğrulaması ekleyebilirsiniz:

_ASSERT(numMols >= 0);

Programınız doğru şekilde çalışıyorsa bu deyimler hiçbir şey yapmaz. Ancak bir mantıksal hata numMols'ün sıfırdan küçük olmasına neden olursa, onaylama işlemi programınızın yürütülmesini durdurur ve Doğrulama Başarısız İletişim Kutusu görüntülenir.

Bu başlıkta

Sonuçlar denetleniyor

Onaylar, sonuçları hızlı bir görsel incelemeden belli olmayan test işlemleri için değerlidir.

Örneğin, aşağıdaki kodun mols tarafından işaret edilen bağlı listenin içeriğine göre iMols değişkenini nasıl güncellediğini göz önünde bulundurun:

/* This code assumes that type has overloaded the != operator
 with const char *
It also assumes that H2O is somewhere in that linked list.
Otherwise we'll get an access violation... */
while (mols->type != "H2O")
{
    iMols += mols->num;
    mols = mols->next;
}
ASSERT(iMols<=numMols); // MFC version
_ASSERT(iMols<=numMols); // CRT version

tarafından iMols sayılan moleküllerin sayısı her zaman toplam molekül sayısına eşit veya daha az olmalıdır. numMols Döngünün görsel incelemesi bunun mutlaka böyle olacağını göstermez, bu nedenle döngüden sonra bu koşulu test etmek için bir onay deyimi kullanılır.

Bu başlıkta

İşlenmeyen hataları bulma

Kodunuzda hataların işlenmiş olması gereken bir noktada hata koşullarını test etmek için doğrulama ifadelerini kullanabilirsiniz. Aşağıdaki örnekte, grafik yordamı bir hata kodu veya başarı için sıfır döndürür.

myErr = myGraphRoutine(a, b);

/* Code to handle errors and
   reset myErr if successful */

ASSERT(!myErr); -- MFC version
_ASSERT(!myErr); -- CRT version

Hata işleme kodu düzgün çalışıyorsa, onaya ulaşılmadan önce hata işlenmeli ve myErr sıfıra sıfırlanmalıdır. Başka bir değere sahipse myErr onay başarısız olur, program durdurulür ve Onay Başarısız İletişim Kutusu görüntülenir.

Ancak onay deyimleri, hata işleme kodunun yerine geçmez. Aşağıdaki örnekte, son sürüm kodunda sorunlara yol açabilecek bir onay deyimi gösterilmektedir:

myErr = myGraphRoutine(a, b);

/* No Code to handle errors */

ASSERT(!myErr); // Don't do this!
_ASSERT(!myErr); // Don't do this, either!

Bu kod, hata koşulunu işlemek için onay deyimine dayanır. Sonuç olarak, myGraphRoutine tarafından döndürülen tüm hata kodları son sürüm kodunda ele alınmayacaktır.

Bu başlıkta