Aracılığıyla paylaş


C/C++ Onayları

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 onayları.

  • ATL kullanan programlar için ATLASSERT .

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

  • 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 onaylar

Onayları kullanmanın yan etkileri

CRT onayları

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ı penceresindehem 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 onay kullanın.

Bu konuda

Hata Ayıklama ve Yayın derlemelerindeki onaylar

Onay deyimleri yalnızca tanımlandığında _DEBUG derleniyor. Aksi takdirde, derleyici onayları null deyimleri olarak kabul eder. Bu nedenle, onay deyimleri son Sürüm programınızda ek yük veya performans maliyeti getirmez ve yönergeleri kullanmaktan #ifdef kaçınmanıza olanak sağlar.

Onayları kullanmanın yan etkileri

Kodunuza onaylar eklediğinizde onayların yan etkileri olmadığından emin olun. Örneğin, değeri değiştiren aşağıdaki onaylama işlemini nM 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 çağrılar myFnctn , bu nedenle kullanılması kabul edilebilir. Ancak, kullanmak VERIFY , Sürüm sürümünde gereksiz bir işlev çağrısının yükünü getirir.

Bu konuda

CRT onayları

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

Makro Sonuç
_ASSERT Belirtilen ifade YANLIŞ olarak değerlendirilirse, dosya adı ve satır numarası _ASSERT.
_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ü kullanılarak _ASSERTEonaylanan her 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 .

Tanımlandığında _DEBUG , _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, onay hatasını bildirmek için _CrtDbgReport çağrılır (varsayılan olarak bir ileti iletişim kutusu kullanılarak). İ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.

Tüm onayları geçici olarak devre dışı bırakmanız gerekiyorsa _CtrSetReportMode kullanın.

Yığın Bozulması Denetleniyor

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, yerel yığındaki belleğe işaret eden bir işaretçiyi 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), DLL'nin kitaplığın kendi örneği ve dolayısıyla uygulama yığını dışında kendi yığını olabilir). Bu onay 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 konum dışı 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 konuda

MFC onayları

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

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ıya bölünmesine 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ı öğesinden CObjecttürerken geçersiz kılmanız AssertValid 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 bildir olduğu 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 nesneleri depolarsa, makroyu ASSERT_VALID kullanarak iç geçerliliklerini test edebilirsiniz (sınıfları geçersiz kılarsa AssertValid).

Örneğin, bir CObList öğesini üye değişkenlerinden birinde depolayan bir sınıfını CMyDatagö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 ...
};

içindeki AssertValidCMyData geçersiz kılma şöyle 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

CMyDataAssertValid, 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.

Sınıfı CObList da geçersiz kıldığından AssertValidgeçerlilik testi bu düzeyde durdurulmuyor. Bu geçersiz kılma, listenin iç durumunda ek geçerlilik testi gerçekleştirir. 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. öğesinden CObList bir sınıf CPersonList türetebilir ve geçersiz kılabilirsinizAssertValid. Geçersiz kılmada, listede depolanan her CPerson nesnede çağırarak AssertValid listeyi çağırıp CObject::AssertValid yinelersiniz. CPerson Bu konunun başında gösterilen sınıf zaten geçersiz kılarAssertValid.

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 konuda

Onayları kullanma

Mantıksal hataları yakalama

Programınızın mantığına göre doğru olması gereken bir koşulda onay 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);

Bunun gibi bir CRT onayı da ekleyebilirsiniz:

_ASSERT(numMols >= 0);

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

Bu konuda

Sonuçlar denetleniyor

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

Örneğin, değişkeni tarafından işaret edilen molsbağlı listenin içeriğine göre güncelleştiren iMols aşağıdaki kodu 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 konuda

İşlenmeyen hataları bulma

Onayları kullanarak kodunuzda hataların işlenmesi gereken bir noktada hata koşullarını test edebilirsiniz. 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, tarafından myGraphRoutine döndürülen tüm hata kodları son sürüm kodunda işlenmemiş olur.

Bu konuda