Megosztás a következőn keresztül:


CRT hibakeresési technikák

A C futásidejű kódtárat használó programok hibakeresésekor ezek a hibakeresési technikák hasznosak lehetnek.

CRT hibakeresési kódtár használata

A C futtatókörnyezeti (CRT) kódtár széles körű hibakeresési támogatást nyújt. A CRT hibakeresési kódtárak egyikének használatához csatolnia /DEBUG kell, és össze kell állítania az /MDd, /MTdvagy /LDd.

A CRT-hibakeresés fő definíciói és makrói a <crtdbg.h> fejlécfájlban találhatók.

A CRT hibakeresési kódtárak funkciói hibakeresési adatokkal (/Z7, /Zd, /Zi, /ZI (Hibakeresési információformátum)) vannak lefordítva, optimalizálás nélkül. Egyes függvények állításokat tartalmaznak a nekik átadott paraméterek ellenőrzéséhez, és a forráskód meg van adva. Ezzel a forráskóddal a CRT-függvényekbe lépve ellenőrizheti, hogy a függvények a várt módon működnek-e, és ellenőrizze, hogy nincsenek-e rossz paraméterek vagy memóriaállapotok. (Egyes CRT-technológia védett, és nem biztosít forráskódot a kivételkezeléshez, a lebegőpontos és néhány egyéb rutinhoz.)

A különböző futásidejű kódtárakról további információt a C Run-Time-kódtárak című témakörben talál.

Makrók jelentéskészítéshez

A hibakereséshez használhatja a _RPTn benne _RPTFndefiniált makrókat és <crtdbg.h> makrókat az utasítások használatáraprintf. Nem kell azokat irányelvekbe #ifdef ágyaznia, mert azok automatikusan eltűnnek a kiadási buildben, ha _DEBUG nincs definiálva.

Makró Leírás
_RPT0, _RPT1, _RPT2, _RPT3_RPT4 Egy üzenetsztringet és 0–4 argumentumot ad ki. _RPT1Az _RPT4 üzenetsztring végig az argumentumok printf stílusú formázási sztringjeként szolgál.
_RPTF0, _RPTF1, _RPTF2, _RPTF3_RPTF4 Ugyanaz, mint _RPTn, de ezek a makrók a fájlnevet és a sorszámot is kimenetként használják, ahol a makró található.

Vegye figyelembe a következő példát:

#ifdef _DEBUG
    if ( someVar > MAX_SOMEVAR )
        printf( "OVERFLOW! In NameOfThisFunc( ),
               someVar=%d, otherVar=%d.\n",
               someVar, otherVar );
#endif

Ez a kód a következő értékeket someVarotherVarstdoutadja ki: A következő hívással _RPTF2 ugyanezeket az értékeket, valamint a fájlnevet és a sorszámot is jelentheti:

if (someVar > MAX_SOMEVAR) _RPTF2(_CRT_WARN, "In NameOfThisFunc( ), someVar= %d, otherVar= %d\n", someVar, otherVar );

Előfordulhat, hogy egyes alkalmazások hibakeresési jelentést igényelnek, amelyeket a C futásidejű tárhoz megadott makrók nem biztosítanak. Ezekben az esetekben olyan makrót írhat, amely kifejezetten a saját igényeinek megfelelően lett kialakítva. Az egyik fejlécfájlban például az alábbihoz hasonló kóddal definiálhat egy úgynevezett ALERT_IF2makrót:

#ifndef _DEBUG                  /* For RELEASE builds */
#define  ALERT_IF2(expr, msg, arg1, arg2)  do {} while (0)
#else                           /* For DEBUG builds   */
#define  ALERT_IF2(expr, msg, arg1, arg2) \
    do { \
        if ((expr) && \
            (1 == _CrtDbgReport(_CRT_ERROR, \
                __FILE__, __LINE__, msg, arg1, arg2))) \
            _CrtDbgBreak( ); \
    } while (0)
#endif

Egy hívással ALERT_IF2 elvégezheti a kód összes függvényét printf :

ALERT_IF2(someVar > MAX_SOMEVAR, "OVERFLOW! In NameOfThisFunc( ),
someVar=%d, otherVar=%d.\n", someVar, otherVar );

Az egyéni makrókat egyszerűen módosíthatja úgy, hogy több vagy kevesebb információt jelentsenek különböző célhelyekre. Ez a módszer a hibakeresési követelmények fejlődésével együtt hasznos.

Horogfüggvény írásának hibakeresése

Többféle egyéni hibakeresési horogfüggvényt is írhat, amelyekkel beszúrhatja a kódot a hibakereső normál feldolgozásának bizonyos előre meghatározott pontjaiba.

Ügyfélblokkok horogfüggvényei

Ha ellenőrizni vagy jelenteni szeretné a blokkokban _CLIENT_BLOCK tárolt adatok tartalmát, kifejezetten erre a célra írhat függvényt. Az ön által írt függvénynek a következőhöz hasonló prototípussal kell rendelkeznie, a következőben meghatározott módon <crtdbg.h>:

void YourClientDump(void *, size_t)

Más szóval a horogfüggvénynek el kell fogadnia a void foglalási blokk elejére mutató mutatót, valamint egy típusértéket size_t , amely a foglalás méretét jelzi, és visszaadja a függvényt void. Ellenkező esetben a tartalma Önön múlik.

Miután telepítette a horogfüggvényt _CrtSetDumpClient használatával, a rendszer minden alkalommal meghívja, amikor egy _CLIENT_BLOCK blokkot dobnak. Ezután a _CrtReportBlockType használatával információkat kaphat a dömpingelt blokkok típusáról vagy altípusáról.

A függvénynek átadott _CrtSetDumpClient mutató típusa a következőben _CRT_DUMP_CLIENTmeghatározott:<crtdbg.h>

typedef void (__cdecl *_CRT_DUMP_CLIENT)
   (void *, size_t);

Kiosztási horogfüggvények

A rendszer minden alkalommal meghív egy foglalási horogfüggvényt, amelyet a rendszer _CrtSetAllocHookminden alkalommal meghív, amikor a rendszer lefoglalja, újraosztja vagy felszabadítja a memóriát. Ezt a típusú horogot számos különböző célra használhatja. Segítségével tesztelheti, hogy egy alkalmazás hogyan kezeli az elégtelen memóriahelyzeteket, például a foglalási mintákat vagy a naplólefoglalási információkat későbbi elemzéshez.

Megjegyzés:

Vegye figyelembe a C futtatókörnyezeti kódtárfüggvények foglalási horogfüggvényekben való használatára vonatkozó korlátozást, amelyet a Kiosztási horgok és a crt memóriafoglalások című cikkben ismertetünk.

A foglalási horogfüggvénynek az alábbi példához hasonló prototípussal kell rendelkeznie:

int YourAllocHook(int nAllocType, void *pvData,
        size_t nSize, int nBlockUse, long lRequest,
        const unsigned char * szFileName, int nLine )

Az átadott _CrtSetAllocHook mutató típusa a következőben _CRT_ALLOC_HOOKmeghatározott:<crtdbg.h>

typedef int (__cdecl * _CRT_ALLOC_HOOK)
    (int, void *, size_t, int, long, const unsigned char *, int);

Amikor a futásidejű kódtár meghívja a horgot, az nAllocType argumentum jelzi, hogy milyen foglalási műveletet kell végrehajtani (_HOOK_ALLOC_HOOK_REALLOCvagy_HOOK_FREE). Szabad vagy átcsoportosítás pvData esetén a felszabadítani kívánt blokk felhasználói cikkére mutató mutató található. Foglalás esetén azonban ez a mutató null értékű, mert a foglalás nem történt meg. A fennmaradó argumentumok tartalmazzák a foglalás méretét, blokktípusát, szekvenciális kérelemszámát és a fájlnévre mutató mutatót. Ha elérhető, az argumentumok tartalmazzák azt a sorszámot is, amelyben a foglalás történt. Miután a horogfüggvény bármilyen elemzést és más feladatot végrehajt, amelyet a szerző kíván, vagy azt kell visszaadnia TRUE, hogy a foglalási művelet folytatódhat, vagy FALSEazt jelzi, hogy a műveletnek sikertelennek kell lennie. Egy ilyen típusú egyszerű horog ellenőrizheti az eddig lefoglalt memória mennyiségét, és visszaadhatja FALSE , ha ez az összeg túllépett egy kis korlátot. Az alkalmazás ekkor olyan foglalási hibákat tapasztal, amelyek általában csak akkor fordulnak elő, ha a rendelkezésre álló memória alacsony. Az összetettebb horgok nyomon követhetik a foglalási mintákat, elemezhetik a memóriahasználatot, vagy jelentést kaphatnak adott helyzetekben.

Foglalási horgok és CRT-memóriafoglalások

A kiosztási horogfüggvények fontos korlátozása, hogy explicit módon figyelmen kívül kell hagyniuk _CRT_BLOCK a blokkokat. Ezek a blokkok a C futásidejű könyvtárfüggvények által belsőleg végrehajtott memóriafoglalások, ha a belső memóriát lefoglaló C futásidejű kódtárfüggvényekre irányuló hívásokat kezdeményeznek. A blokkokat figyelmen kívül hagyhatja _CRT_BLOCK úgy, hogy az alábbi kódot a foglalási horogfüggvény elején adja meg:

if ( nBlockUse == _CRT_BLOCK )
    return( TRUE );

Ha a kiosztási horog nem hagyja figyelmen kívül _CRT_BLOCK a blokkokat, akkor a horogban hívott C futásidejű kódtár-függvények végtelen hurokban képesek csapdába ejteni a programot. Például printf belső lefoglalást végez. Ha a horogkód hívások printf, akkor az eredményként kapott lefoglalás hatására a horog újra le lesz hívva, ami újra meghívja printf , és így tovább, amíg a verem túlcsordul. Ha kiosztási műveleteket kell jelentenie _CRT_BLOCK , a korlátozás megkerülésének egyik módja a Windows API-függvények használata a C futásidejű függvények helyett a formázáshoz és a kimenethez. Mivel a Windows API-k nem használják a C futásidejű kódtár halomát, nem fogják végtelen hurokba csapni a foglalási horgot.

Ha megvizsgálja a futásidejű kódtár forrásfájljait, látni fogja, _CrtDefaultAllocHook hogy az alapértelmezett foglalási horogfüggvény (amely egyszerűen visszaadjaTRUE) egy külön, saját fájlban található. debug_heap_hook.cpp Ha azt szeretné, hogy a kiosztási horog még az alkalmazás függvénye main előtt végrehajtott futásidejű indítási kód által végrehajtott foglalások esetében is le legyen hívva, ezt az alapértelmezett függvényt lecserélheti egy sajátra ahelyett, hogy használna _CrtSetAllocHook.

Jelentéshoomfüggvények

A jelentéshohorog függvényt a rendszer _CrtSetReportHookminden alkalommal meghívja, amikor _CrtDbgReport hibakeresési jelentést hoz létre. Többek között arra is használhatja, hogy a jelentések szűrésével bizonyos foglalástípusokra összpontosítson. A jelentéshook-függvénynek az alábbi példához hasonló prototípussal kell rendelkeznie:

int AppReportHook(int nRptType, char *szMsg, int *retVal);

Az átadott _CrtSetReportHook mutató típusa a következőben _CRT_REPORT_HOOKmeghatározott:<crtdbg.h>

typedef int (__cdecl *_CRT_REPORT_HOOK)(int, char *, int *);

Amikor a futásidejű kódtár meghívja a horogfüggvényt, az nRptType argumentum a jelentés kategóriáját (_CRT_WARN_CRT_ERRORvagy _CRT_ASSERT) szMsg egy teljesen összeállított jelentésüzenet-sztringre mutató mutatót tartalmaz, és retVal megadja, hogy a jelentés létrehozása vagy a hibakereső elindítása után folytatnia kell-e _CrtDbgReport a normál végrehajtást. (A retVal nulla érték folytatja a végrehajtást, az 1 érték elindítja a hibakeresőt.)

Ha a horog teljesen kezeli a szóban forgó üzenetet, így nincs szükség további jelentésre, akkor vissza kell térnie TRUE. Ha visszaérkezik FALSE, _CrtDbgReport akkor az üzenet a szokásos módon jelenik meg.

Ebben a szakaszban

  • A halomfoglalási függvények verzióinak hibakeresése

    A halomfoglalási függvények speciális hibakeresési verzióit ismerteti, többek között a következőkről: a CRT hívásokat képez le, milyen előnyökkel jár, ha kifejezetten meghívja őket, hogyan kerülheti el az átalakítást, hogyan követheti nyomon a különböző típusú foglalásokat az ügyfélblokkokban, valamint a nem definiált _DEBUGeredmények.

  • CRT hibakeresési halom részletei

    Ismerteti a memóriakezelést és a hibakeresési halomot, a hibakeresési halom blokkjainak típusait, a halomállapot-jelentési függvényeket, valamint a hibakeresési halom használatát a foglalási kérelmek nyomon követéséhez.

  • Memóriavesztések keresése a CRT-kódtár használatával

    A memóriaszivárgások észlelésére és elkülönítésére szolgáló technikákat ismerteti a hibakereső és a C Run-Time könyvtár használatával.

Lásd még