Udostępnij za pośrednictwem


Potwierdzeń

Instrukcja assertion określa warunek, które mają być spełnione w momencie w programie.Jeśli ten warunek nie zostanie spełniony, twierdzenie nie powiedzie się, wykonanie tego programu zostanie przerwane, a okno dialogowe Assertion Failed pojawi się.

Visual C++ obsługuje instrukcji assertion, które opierają się na następujące elementy:

  • Twierdzenia MFC dla aplikacji MFC.

  • ATLASSERT dla programów, które używają ATL

  • Twierdzenia CRT dla programów, które używają biblioteki uruchomieniowej C.

  • ANSI dochodzić funkcji w przypadku innych programów C/C++.

Twierdzenia służy wychwytywanie błędów logiki, sprawdź wyniki operacji i warunki błędów, które zostały obsłużone należy przetestować.

W tym temacie

Jak działają potwierdzeń

Twierdzenia w buduje Debug i Release

Przy pomocy twierdzenia skutki uboczne

Twierdzenia CRT

Twierdzenia MFC

  • MFC ASSERT_VALID i CObject::AssertValid

  • Ograniczenia AssertValid

Przy pomocy twierdzenia

  • Połowu błędy logiczne

  • Weryfikacja wyników

  • Błędy niezgodności z nieobsługiwanym

Jak działają potwierdzeń

Gdy debuger zostanie zatrzymany z powodu assertion biblioteki MFC lub C, jeśli źródło jest niedostępny, debuger przejdzie do punktu w pliku źródłowym, w którym wystąpiło twierdzenie.Zostanie wyświetlony komunikat potwierdzenia w obu okna dane wyjściowe i Assertion Failed okno dialogowe.Można skopiować wiadomość potwierdzenia od produkcji okno, aby okno tekstowe, aby zapisać go do użytku w przyszłości.Produkcji okno może zawierać również inne komunikaty.Zbadać te komunikaty ostrożnie, ponieważ stanowią one wskazówek, aby spowodować błąd potwierdzenia.

Użyj twierdzenia do wykrywania błędów w czasie projektowania.Zasadą jest Użyj jednego potwierdzenia dla każde założenie.Na przykład jeśli założyć, że argument nie jest NULL, umożliwia podanie przetestować założeniu, że.

W tym temacie

Twierdzenia w buduje Debug i Release

Instrukcje Assertion skompilować tylko wtedy, gdy _DEBUG jest zdefiniowany.W przeciwnym razie kompilator traktuje twierdzenia jako ustalanie wartości null.W związku z tym, instrukcje assertion nałożyć nie ma nad głową lub wydajności kosztów w programie do ostatecznego wydania i pozwala unikać #ifdef dyrektyw.

Przy pomocy twierdzenia skutki uboczne

Po dodaniu twierdzenia do kodu, należy upewnić się, czy twierdzenia o uzyskaniu nie mają skutki uboczne.Na przykład, rozważmy następujące stwierdzenie, że modyfikuje nM wartość:

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

Ponieważ ASSERT w wersji tego programu, nie jest obliczane wyrażenie nM mają różne wartości w wersjach Debug i Release.Aby uniknąć tego problemu w MFC, można użyć WERYFIKUJ makro, a nie ASSERT.VERIFYwyznacza wartość wyrażenia we wszystkich wersjach, ale nie sprawdza wynik w wersji wydania.

Uważaj szczególnie używając wywołań funkcji w sprawozdaniu assertion, ponieważ funkcji może mieć nieoczekiwane działania niepożądane.

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

VERIFYwywołania myFnctn w wersji Debug i Release, czyli można zastosować.Jednakże, przy pomocy VERIFY o wywołanie funkcji niepotrzebnych w wersji wydania.

W tym temacie

Twierdzenia CRT

CRTDBG.H plik nagłówkowy definiuje _ASSERT i _ASSERTE makra sprawdzania twierdzenie.

Makro

Wynik

_ASSERT

Jeśli określone wyrażenie zwróci wartość FAŁSZ, nazwy i linii numer akt _ASSERT.

_ASSERTE

Taki sam jak _ASSERT, plus reprezentację ciąg wyrażenia, które zostało potwierdzone.

_ASSERTEjest bardziej wydajne, ponieważ przekazuje rzekoma wyrażenie, które okazały się być FALSE.To może wystarczyć, aby zidentyfikować problem bez odnoszenia się do kodu źródłowego.Jednak program Debug wersję swojej aplikacji będzie zawierać to stała ciągu dla każdego wyrażenia potwierdzony za pomocą _ASSERTE.Jeśli używasz wielu _ASSERTE makr, te wyrażenia ciągu zajmować znaczną ilość pamięci.Jeśli okaże się to być problem, użyj _ASSERT zapisać w pamięci.

Gdy _DEBUG jest zdefiniowana, _ASSERTE makro jest zdefiniowane w następujący sposób:

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

Jeśli rzekoma wyrażenie ma wartość FALSE, _CrtDbgReport nazywa się zgłosić błąd potwierdzenia (przy użyciu jest okno dialogowe domyślnie).Jeśli wybierzesz ponowić próbę w oknie dialogowym komunikatu _CrtDbgReport zwraca wartość 1, i _CrtDbgBreak wywołuje debuger przez DebugBreak.

ww5t02fa.collapse_all(pl-pl,VS.110).gifSprawdzanie sterty jest uszkodzony

W poniższym przykładzie użyto _CrtCheckMemory Aby sprawdzić, czy uszkodzenie sterty:

_ASSERTE(_CrtCheckMemory());

ww5t02fa.collapse_all(pl-pl,VS.110).gifKontroli wskaźnik ważności

W poniższym przykładzie użyto _CrtIsValidPointer Aby sprawdzić, czy zakres danej pamięci jest prawidłowa do odczytu lub zapisu.

_ASSERTE(_CrtIsValidPointer( address, size, TRUE );

W poniższym przykładzie użyto _CrtIsValidHeapPointer do Sprawdź wskaźnik wskazuje pamięci na stercie lokalnego (sterty tworzony i zarządzany przez to wystąpienie biblioteki uruchomieniowej C — Biblioteka DLL może mieć własne wystąpienie biblioteki, a tym samym swojej własnej sterty, poza sterty aplikacji).Twierdzenie to nie połów tylko wartość null lub zdalne adresy, ale również wskaźniki do zmiennych statycznych, zmiennych stosu i innych nielokalne pamięci.

_ASSERTE(_CrtIsValidPointer( myData );

ww5t02fa.collapse_all(pl-pl,VS.110).gifSprawdzanie bloku pamięci

W poniższym przykładzie użyto _CrtIsMemoryBlock Aby zweryfikować, że blok pamięci jest lokalna sterta i ma typ nieprawidłowy blok.

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

W tym temacie

Twierdzenia MFC

Definiuje MFC ASSERT makro sprawdzania twierdzenie.Definiuje również MFC ASSERT_VALID i CObject::AssertValid metod kontrolowania wewnętrznego stanu CObject-pochodnych obiektu.

Jeśli argument MFC ASSERT makro daje w wyniku wartość zero lub wartość false, makro przerywa wykonywania programu i powiadamia użytkownika; w przeciwnym razie kontynuuje wykonywanie.

Kiedy podanie nie, jest okno dialogowe zawiera nazwę pliku źródłowego oraz numer wiersza twierdzenie.Jeżeli wybierz przycisk Ponów w oknie dialogowym pole, wywołanie AfxDebugBreak powoduje wykonanie do debugera.W tym momencie można zbadać stos wywołań i korzystania z innych urządzeń debugger Aby ustalić, dlaczego twierdzenie nie powiodło się.Jeśli włączono debugowania Just in timei debuger nie został jeszcze uruchomiony, okno dialogowe można uruchomić debugera.

Poniższy przykład pokazuje, jak używać ASSERT do sprawdzenia zwracanej wartości funkcji:

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

Można użyć ASSERT z IsKindOf funkcji typ sprawdzania argumentów funkcji:

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

ASSERT Makro generuje żadnego kodu w wersji wydania.Jeśli konieczne jest oszacowanie wyrażenia w wydanej wersji, należy użyć WERYFIKUJ makro zamiast ASSERT.

ww5t02fa.collapse_all(pl-pl,VS.110).gifMFC ASSERT_VALID i CObject::AssertValid

CObject::AssertValid metoda zapewnia wykonania kontroli wewnętrznej stan obiektu.Chociaż nie jest wymagane Aby zastąpić AssertValid kiedy pochodzić od klasy CObject, można dokonać bardziej niezawodne klasy w ten sposób.AssertValidnależy wykonać potwierdzeń na wszystkie zmienne składowe tego obiektu, aby zweryfikować, że zawierają one prawidłowych wartości.Na przykład należy sprawdzić, że wskaźnik zmienne składowe nie mają wartości NULL.

Poniższy przykład pokazuje, jak zadeklarować AssertValid funkcji:

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

Kiedy można zastąpić AssertValid, Wywołaj wersję klasy bazowej AssertValid przed wykonaniem własne kontrole.Następnie użyć makra ASSERT, aby sprawdzić członków unikatowe dla swojej klasie pochodnej, jak pokazano poniżej:

#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

Jeśli którykolwiek z swoje zmienne składowe przechowywania obiektów, można użyć ASSERT_VALID makro, aby ich wewnętrzne ważność badania (jeśli ich klasy zastępują AssertValid).

Rozważmy na przykład klasy CMyData, które sklepy CObList w jednym z jego zmienne składowe.CObList Zmiennej, m_DataList, przechowywana kolekcja CPerson obiektów.Deklaracja skrócona CMyData wygląda następująco:

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 Zastąpić w CMyData wygląda następująco:

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

CMyDataużywa AssertValid mechanizmu, aby sprawdzić poprawność obiekty przechowywane w jego członka danych.Nadrzędny AssertValid z CMyData wywołuje ASSERT_VALID makro dla własną zmienną m_pDataList.

Ważność badania nie zatrzymuje się na tym poziomie ponieważ klasy CObList zastępuje również AssertValid.Ta override wykonuje dodatkowe ważność badań przeprowadzanych na wewnętrznego stanu listy.W ten sposób, ważności badania na CMyData obiektu prowadzi ważność dodatkowych badań wewnętrznych Państwa przechowywane do CObList obiektu list.

Z trochę więcej pracy, to można dodać test zgodności dla CPerson obiektów również przechowywane na liście.Może pochodzić od klasy CPersonList z CObList i zastąpić AssertValid.W override, wywołana zostałaby CObject::AssertValid i następnie iteracyjne przeglądanie listy, wywołanie AssertValid na każdym CPerson obiektu przechowywane na liście.CPerson Się na początku tego tematu już klasa zastępuje AssertValid.

Jest to potężny mechanizm podczas konstruowania do debugowania.Gdy następnie zbudować dopuszczenia, mechanizm jest automatycznie wyłączane.

ww5t02fa.collapse_all(pl-pl,VS.110).gifOgraniczenia AssertValid

Wyzwalane assertion wskazuje, że obiekt jest zdecydowanie zły i wykonanie zostanie zatrzymane.Jednak brak potwierdzenia wskazuje się tylko nie znaleziono problemów, że obiekt nie jest zapewniona jest dobra.

W tym temacie

Przy pomocy twierdzenia

ww5t02fa.collapse_all(pl-pl,VS.110).gifPołowu błędy logiczne

Podanie można ustawić, pod warunkiem, że muszą zostać spełnione zgodnie z logiką tego programu.Twierdzenie jest ignorowany, chyba że występuje błąd logiczny.

Załóżmy na przykład, symulują cząsteczek gazu w pojemniku i zmiennej numMols — łączną liczbę cząsteczek.Liczba ta nie może być mniejsza od zera, więc może zawierać instrukcję assertion MFC tak:

ASSERT(numMols >= 0);

Lub może zawierać assertion CRT w następujący sposób:

_ASSERT(numMols >= 0);

Instrukcje te zrobić nic, jeśli program działa poprawnie.Jeśli błąd logiczny powoduje, że numMols do być mniejsza od zera, jednak potwierdzenie zatrzymuje wykonywanie tego programu i wyświetla Okno dialogowe potwierdzenia, nie powiodło się.

W tym temacie

ww5t02fa.collapse_all(pl-pl,VS.110).gifWeryfikacja wyników

Twierdzenia mają duże znaczenie dla testowania operacje, których wyniki nie są oczywiste z szybkiego oględziny.

Na przykład, rozważmy następujący kod, który aktualizuje zmiennej iMols na podstawie zawartości połączonej listy wskazywanej przez mols:

/* 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

Kryterium liczenia liczby cząsteczek iMols zawsze musi być mniejsza niż całkowita liczba cząsteczek, numMols.Oględziny pętli nie pokazuje, że niekoniecznie będzie to przypadek, więc instrukcja assertion jest używany po pętli, aby przetestować związane z tym warunkiem.

W tym temacie

ww5t02fa.collapse_all(pl-pl,VS.110).gifBłędy niezgodności z nieobsługiwanym

Twierdzenia można użyć do sprawdzenia warunków błędów w punkcie w kodzie, gdzie wszelkie błędy powinny były przeładowywane.W poniższym przykładzie graficzny rutynowych zwraca kod błędu lub wartość zero dla sukcesu.

myErr = myGraphRoutine(a, b);

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

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

Jeśli kod obsługi błędów działa prawidłowo, powinno się obchodzić błędu i myErr reset do zera przed osiągnięciem twierdzenie.Jeśli myErr ma inną wartość, kończy się niepowodzeniem assertion, zatrzymanie programu i Okno dialogowe potwierdzenia, nie powiodło się jest wyświetlany.

Instrukcje potwierdzenia nie są jednak substytut kod obsługi błędów.Instrukcja assertion, która może prowadzić do problemów w kodzie ostatecznej wersji można znaleźć w poniższym przykładzie:

myErr = myGraphRoutine(a, b);

/* No Code to handle errors */

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

Ten kod opiera się na wyciągu assertion, aby obsługiwać warunek błędu.W rezultacie kod błędu zwrócony przez myGraphRoutine będzie nieobsłużonych w kodzie wersja ostateczna.

W tym temacie

Zobacz też

Informacje

Potwierdzeń w kodzie zarządzanym.

Koncepcje

Debuger zabezpieczeń

Inne zasoby

Debugowanie kodu macierzystego