Sdílet prostřednictvím


Kontrolní výrazy jazyka C/C++

Příkaz výrazu Určuje podmínku, která budete chtít platit na místě v aplikaci.Pokud tato podmínka není splněna, výraz se nezdaří, dojde k přerušení programu a Chyba při vyhodnocení dialogové se objeví.

Visual C++ podporuje tvrzení příkazy, které jsou založeny na následujících konstrukcí:

  • Kontrolní výrazy MFC pro aplikace knihovny MFC.

  • ATLASSERT pro programy, které používají knihovnu ATL.

  • CRT výrazy pro programy, které používají knihovny běhu jazyka C.

  • ANSI vyhodnocení funkce pro ostatní programy C/C++.

Výrazy můžete použít k zachycení chyb logiky, zkontrolovat výsledky operace a testování chybových stavů, které by byly zpracovány.

V tomto tématu

Práce s výrazy

Kontrolní výrazy v Debug a Release sestavení

Vedlejší účinky používání výrazy

Kontrolní výrazy CRT

Kontrolní výrazy knihovny MFC

  • MFC ASSERT_VALID a CObject::AssertValid

  • Omezení AssertValid

Používat výrazy

  • Zachycení chyb logiky

  • Kontrola výsledků

  • Testování chybových stavů

Práce s výrazy

Pokud ladicí program zastaví z důvodu nepravdivých běhové knihovny MFC nebo knihovny C, pak pokud je zdroj k dispozici ladicí program přejde ve zdrojovém souboru, kde došlo k kontrolní bod.Výraz zobrazí v obou okno výstup a Chyba při vyhodnocení dialogové okno.Můžete zkopírovat výraz sdělení výstup okna do okna text, pokud chcete uložit pro pozdější použití.Výstup okno může obsahovat další chybové zprávy.Tyto zprávy zkontrolujte pečlivě, protože poskytují vodítko k příčině selhání výrazu.

Výrazy používají ke zjišťování chyb během vývoje.Jako pravidlo použijte pro každý předpoklad jeden výraz.Předpokladu, že argument není nula, například pomocí nepravdivých testování tohoto předpokladu.

V tomto tématu

Kontrolní výrazy v Debug a Release sestavení

Kompilovat výraz příkazy pouze tehdy, pokud _DEBUG je definován.Jinak kompilátor zpracovává výrazy jako null příkazy.Proto výraz příkazy uložit žádné nároky ani výkonu nákladů v konečné verzi programu a vyhnete se pomocí #ifdef směrnice.

Vedlejší účinky používání výrazy

Přidáte-li výrazy v kódu, ověřte, zda že tvrzení nemají vedlejší účinky.Zvažte například následující výraz, který mění nM hodnotu:

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

Protože ASSERT výrazu není vyhodnocena ve verzi programu, nM v Debug a Release verze budou mít různé hodnoty.Chcete-li zabránit tomuto problému v knihovně MFC, použijte Ověřit makra namísto ASSERT. VERIFYvyhodnotí výraz ve všech verzích, ale nekontroluje výsledek ve vydané verzi.

Buďte obzvlášť opatrní použití volání funkce v výraz DDL, protože vyhodnocení funkce může mít neočekávané vedlejší účinky.

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

VERIFYvolání myFnctn Debug a Release verze, tak je přijatelné použít.Však pomocí VERIFY ukládá režii volání funkce zbytečné ve vydané verzi.

V tomto tématu

Kontrolní výrazy CRT

CRTDBG.Definuje soubor hlaviček H makra _ASSERT a _ASSERTE pro kontrolu výraz.

Makro

Výsledek

_ASSERT

Je-li zadaný výraz vyhodnocen jako NEPRAVDA, soubor název a řádku číslo _ASSERT.

_ASSERTE

Stejné jako _ASSERT, plus řetězcové vyjádření výrazu, která byla uplatněna.

_ASSERTEje mnohem snazší, protože oznámí uplatňovaného výraz, který je FALSE.To může stačit k identifikaci problému bez odkazu na zdrojový kód.Ladicí verze aplikace však obsahuje pro každý výraz uplatněna pomocí řetězcová konstanta _ASSERTE.Pokud používáte mnoho _ASSERTE makra, tyto výrazy řetězec zabírat značné množství paměti.Pokud je to jako problém, použijte _ASSERT k úspoře paměti.

Při _DEBUG je definován _ASSERTE makro je definováno takto:

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

Pokud uplatňovaného výraz vyhodnocen jako NEPRAVDA, _CrtDbgReport se nazývá hlášení selhání vyhodnocení výrazu (pomocí dialogového okna zprávy ve výchozím nastavení).Zvolíte-li Opakovat v dialogovém okně zprávy _CrtDbgReport vrátí hodnotu 1 a _CrtDbgBreak volá debugger pomocí DebugBreak.

Kontrola poškození haldy

Následující příklad používá _CrtCheckMemory pro kontrolu poškození haldy:

_ASSERTE(_CrtCheckMemory());

Kontrola platnosti ukazatele

Následující příklad používá _CrtIsValidPointer k ověření platí rozsah dané paměti pro čtení nebo zápis.

_ASSERTE(_CrtIsValidPointer( address, size, TRUE );

Následující příklad používá _CrtIsValidHeapPointer ověřit ukazatel odkazuje na místní haldy paměti (haldy a spravovány touto instancí běhové knihovny C – knihovna DLL může mít své vlastní instance knihovny, a proto vlastní haldy mimo haldy aplikace).Toto tvrzení úlovky nejsou pouze null nebo out-of-bounds adresy, ale také odkazy na statické proměnné, proměnné zásobníku a další místa paměti.

_ASSERTE(_CrtIsValidPointer( myData );

Kontrola paměti blok

Následující příklad používá _CrtIsMemoryBlock Chcete-li ověřit, že blok paměti haldy místní a má platný blok typu.

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

V tomto tématu

Kontrolní výrazy knihovny MFC

MFC definuje ASSERT makro pro kontrolu výraz.Definuje také MFC ASSERT_VALID a CObject::AssertValid metody pro kontrolu vnitřní stav CObject-odvozené objekt.

Pokud argument knihovny MFC ASSERT makro vyhodnocen jako nula nebo false, makro zastaví provádění programu a upozorní uživatele; v opačném případě se pokračuje.

Když nepravdivých selže, dialogové okno se zprávou se zobrazí název zdrojový soubor a číslo řádku výraz.Pokud tlačítko Opakovat v dialogovém okně pole, volání AfxDebugBreak způsobí spuštění ke vstupu do ladicího programu.V daném okamžiku můžete zkontrolovat zásobník volání a zjistit, proč se nezdařilo výraz pomocí jiných zařízení ladicí program.Pokud jste povolili ladění Just v časa již nebyl spuštěn ladicí program, dialogové okno spustit ladicí program.

Následující příklad ukazuje, jak použít ASSERT Chcete-li zkontrolovat vrácenou hodnotu funkce:

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

Můžete použít metodu ASSERT se IsKindOf funkce můžete zadat typ kontroly argumentů funkce:

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

ASSERT Makra vytváří žádný kód ve vydané verzi.Vyhodnocení výrazu v prodejní verzi, použijte Ověřit makra namísto ASSERT.

MFC ASSERT_VALID a CObject::AssertValid

CObject::AssertValid metoda umožňuje spuštění kontroly vnitřní stav objektu.Přestože není nutné přepsat AssertValid při odvození vaší třídy z CObject, můžete provést vaší třídy spolehlivější tímto způsobem.AssertValidby měly být provedeny kontrolní výrazy všechny členské proměnné objektu, chcete-li ověřit, zda obsahují platné hodnoty.Například by měl zkontrolovat, že ukazatel členské proměnné nejsou NULL.

Následující příklad ukazuje, jak deklarovat AssertValid funkce:

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

Při přepsání AssertValid, verze základní třídy volání AssertValid před provádět vlastní kontroly.Potom pomocí makra ASSERT zkontrolovat členy, které jsou jedinečné pro odvozené třídy, jak je znázorněno zde:

#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

Pokud všechny členské proměnné ukládat objekty, můžete použít ASSERT_VALID makro k testování jejich vnitřní platnosti (pokud jejich třídy potlačí AssertValid).

Zvažte například třídu CMyData, které obchody CObList v jednom z jeho členské proměnné.CObList Proměnná, m_DataList, obsahuje kolekci CPerson objekty.Zkrácený prohlášení CMyData vypadá podobně jako tento:

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 Přepsat v CMyData vypadá podobně jako tento:

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

CMyDatapoužívá AssertValid mechanismus pro testování platnosti objektů uložených v jeho datový člen.Potlačení AssertValid z CMyData vyvolá ASSERT_VALID makro pro vlastní členskou proměnnou m_pDataList.

Testování platnosti nezastaví na této úrovni protože třída CObList také přepíše AssertValid.Toto přepsání provede další platnosti testování na vnitřní stav ze seznamu.Tedy na test platnost CMyData objektu vede k další platnosti zkoušky pro vnitřní stavy uložené CObList objektu list.

Některé další práci můžete přidat platnosti zkoušky CPerson objekty, které jsou také uloženy v seznamu.Může odvodit třídu CPersonList z CObList a AssertValid.V přepsání, volání CObject::AssertValid a potom iterovat seznamu volání AssertValid na každém CPerson objektu, které jsou uloženy v seznamu.CPerson Uvedené na začátku tohoto tématu již třída přepíše AssertValid.

Jedná se o výkonný mechanismus při sestavení pro ladění.Při vytváření následně pro uvolnění, mechanismus je automaticky vypnuta.

Omezení AssertValid

Vyžádané kontrolní výraz označuje, že objekt je jednoznačně chybné a spuštění zastaví.Však nedostatek výraz označuje pouze, že nebyly nalezeny žádné potíže, ale není zaručeno, že objekt být dobré.

V tomto tématu

Používat výrazy

Zachycení chyb logiky

Kontrolní výrazy můžete nastavit na podmínku, která musí být splněna podle logiky aplikace.Výraz nemá žádný účinek, pokud dojde k logické chybě.

Předpokládejme například, že jsou simulace molekul plynu v kontejneru a proměnnou numMols představuje celkový počet molekul.Toto číslo nesmí být menší než nula, tak může obsahovat příkaz knihovny MFC výraz takto:

ASSERT(numMols >= 0);

Nebo může obsahovat CRT výraz takto:

_ASSERT(numMols >= 0);

Tyto příkazy nic dělat, když váš program pracuje správně.Pokud logická chyba způsobí, že numMols být menší než nula, ale výraz zastaví provádění programu a zobrazí Dialogové okno Kontrolní výraz je neplatný.

V tomto tématu

Kontrola výsledků

Výrazy jsou důležité pro testování operací, jejichž výsledky jsou zřejmé z rychlé vizuální kontrole.

Zvažte například následující kód, který aktualizuje proměnné iMols na základě obsahu propojeného seznamu, na kterou odkazuje 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

Počet molekul počítá podle iMols musí být vždy menší než celkový počet molekul, numMols.Vizuální prohlídka smyčky nezobrazuje, že to nutně bude v případě, takže příkaz výrazu se používá po smyčce k testování pro tuto podmínku.

V tomto tématu

Zjištění neošetřené chyby

Použít kontrolní výrazy pro testování kódu chybové podmínky v bodě kde všechny chyby by měly být manipulováno.V následujícím příkladu grafické rutiny vrátí kód chyby nebo nula pro úspěch.

myErr = myGraphRoutine(a, b);

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

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

Pokud kód pro zpracování chyby funguje správně, by měly být zpracovány chyby a myErr na nulu dříve, než je dosaženo výraz obnovení.Pokud myErr má jinou hodnotu, výraz selže, program zdržovalo a Dialogové okno Kontrolní výraz je neplatný se objeví.

Výraz příkazy nejsou však nenahrazuje kód pro zpracování chyb.Následující příklad ukazuje výraz příkazu, který může vést k problémům v konečné verzi kódu:

myErr = myGraphRoutine(a, b);

/* No Code to handle errors */

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

Tento kód se opírá o tvrzení příkaz zpracování chybového stavu.V důsledku toho žádný kód chyby vrácený myGraphRoutine bude ošetřena v konečné verzi kódu.

V tomto tématu

Viz také

Referenční dokumentace

Kontrolní výrazy ve spravovaném kódu

Koncepty

Zabezpečení ladicího programu

Další zdroje

Ladění nativního kódu