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