CRT hata ayıklama teknikleri

C çalışma zamanı kitaplığını kullanan bir programın hatalarını ayıkladığınızda, bu hata ayıklama teknikleri yararlı olabilir.

CRT hata ayıklama kitaplığı kullanımı

C çalışma zamanı (CRT) kitaplığı kapsamlı hata ayıklama desteği sağlar. CRT hata ayıklama kitaplıklarından birini kullanmak için , veya/LDd ile /DEBUG bağlantı oluşturmanız ve derlemeniz /MDd/MTdgerekir.

CRT hata ayıklama için ana tanımlar ve makrolar üst bilgi dosyasında bulunabilir<crtdbg.h> .

CRT hata ayıklama kitaplıklarındaki işlevler hata ayıklama bilgileriyle (/Z7, /Zd, /Zi, /ZI (Hata Ayıklama Bilgileri Biçimi)) ve iyileştirme olmadan derlenir. Bazı işlevler, kendilerine geçirilen parametreleri doğrulamak için onaylar içerir ve kaynak kodu sağlanır. Bu kaynak koduyla, işlevlerin beklediğiniz gibi çalıştığını onaylamak ve hatalı parametreleri veya bellek durumlarını denetlemek için CRT işlevlerine adım atabilirsiniz. (Bazı CRT teknolojileri özeldir ve özel durum işleme, kayan nokta ve diğer birkaç yordam için kaynak kodu sağlamaz.)

Kullanabileceğiniz çeşitli çalışma zamanı kitaplıkları hakkında daha fazla bilgi için bkz . C Çalışma Zamanı Kitaplıkları.

Raporlama makroları

Hata ayıklama için içinde tanımlanan ve _RPTFn makrolarını kullanarak deyimlerin printf kullanımını değiştirebilirsiniz_RPTn<crtdbg.h>. Tanımlanmadığında _DEBUG yayın derlemenizde otomatik olarak kaybolduklarından, bunları #ifdef yönergelere dahil etmeniz gerekmez.

Makro Açıklama
_RPT0, _RPT1, _RPT2, _RPT3, , _RPT4 Bir ileti dizesi ve sıfırdan dörte kadar bağımsız değişken verir. aracılığıyla _RPT1 _RPT4için, ileti dizesi bağımsız değişkenler için printf stili bir biçimlendirme dizesi işlevi görür.
_RPTF0, _RPTF1, _RPTF2, _RPTF3, , _RPTF4 ile _RPTnaynıdır, ancak bu makrolar makronun bulunduğu dosya adını ve satır numarasını da verir.

Aşağıdaki örneği inceleyin:

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

Bu kod, ve otherVar değerlerinin someVar çıkışını verirstdout. Bu değerleri ve ayrıca dosya adını ve satır numarasını bildirmek için _RPTF2 aşağıdaki çağrıyı kullanabilirsiniz:

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

Bazı uygulamaların C çalışma zamanı kitaplığıyla sağlanan makroların sağlamadığını bildiren hata ayıklaması gerekebilir. Bu durumlarda, özel olarak kendi gereksinimlerinize uyacak şekilde tasarlanmış bir makro yazabilirsiniz. Örneğin, üst bilgi dosyalarınızdan birine adlı ALERT_IF2bir makro tanımlamak için aşağıdaki gibi bir kod ekleyebilirsiniz:

#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

bir çağrısı ALERT_IF2 kodun tüm işlevlerini printf gerçekleştirebilir:

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

Özel makroları kolayca değiştirerek farklı hedeflere daha fazla veya daha az bilgi bildirebilirsiniz. Hata ayıklama gereksinimleriniz geliştikçe bu yaklaşım yararlıdır.

Hata ayıklama kanca işlevi yazma

Kodunuzu hata ayıklayıcının normal işlemesinde önceden tanımlanmış bazı noktalara eklemenize olanak sağlayan çeşitli türlerde özel hata ayıklama kancası işlevleri yazabilirsiniz.

İstemci blok kanca işlevleri

Bloklarda _CLIENT_BLOCK depolanan verilerin içeriğini doğrulamak veya raporlamak istiyorsanız, özellikle bu amaçla bir işlev yazabilirsiniz. Yazdığınız işlevin, içinde<crtdbg.h> tanımlandığı gibi aşağıdakine benzer bir prototipi olmalıdır:

void YourClientDump(void *, size_t)

Başka bir deyişle, kanca işleviniz ayırma bloğunun başlangıcına yönelik bir void işaretçiyi kabul etmeli ve ayırmanın boyutunu belirten bir size_t tür değeriyle birlikte döndürmelidir void. Aksi takdirde içeriği size bağlı olur.

Kanca işlevinizi _CrtSetDumpClient kullanarak yükledikten sonra, her _CLIENT_BLOCK blok atıldığında çağrılır. Ardından , _CrtReportBlockType kullanarak atılan blokların türü veya alt türü hakkında bilgi alabilirsiniz.

İşlevinizin işaretçisi_CrtSetDumpClient, içinde tanımlandığı<crtdbg.h> gibi türündedir_CRT_DUMP_CLIENT:

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

Atama kanca işlevleri

kullanılarak _CrtSetAllocHookyüklenen ayırma kancası işlevi, bellek her ayrıldığında, yeniden ayrıldığında veya serbest bırakıldığında çağrılır. Bu tür kancaları birçok farklı amaçla kullanabilirsiniz. Bir uygulamanın, ayırma düzenlerini incelemek veya daha sonra çözümlemek üzere günlük ayırma bilgilerini incelemek gibi yetersiz bellek durumlarını nasıl işlediğini test etmek için bunu kullanın.

Not

Ayırma kancaları ve crt bellek ayırmaları bölümünde açıklanan bir ayırma kanca işlevinde C çalışma zamanı kitaplık işlevlerini kullanma kısıtlamasına dikkat edin.

Ayırma kancası işlevinin aşağıdaki örneğe benzer bir prototipi olmalıdır:

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

Geçirdiğiniz _CrtSetAllocHook işaretçi, içinde<crtdbg.h> tanımlandığı gibi türündedir_CRT_ALLOC_HOOK:

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

Çalışma zamanı kitaplığı kancanızı çağırdığında, nAllocType bağımsız değişken hangi ayırma işleminin (, _HOOK_REALLOCveya _HOOK_FREE) yapılmak_HOOK_ALLOC üzere olduğunu gösterir. Serbest veya yeniden konumlandırmada, pvData serbest olmak üzere olan bloğun kullanıcı makalesine bir işaretçisi vardır. Ancak ayırma işlemi gerçekleşmediğinden bu işaretçi null değeridir. Kalan bağımsız değişkenler ayırmanın boyutunu, blok türünü, sıralı istek numarasını ve dosya adına yönelik bir işaretçiyi içerir. Varsa, bağımsız değişkenler ayırmanın yapıldığı satır numarasını da içerir. Kanca işlevi, yazarının istediği çözümlemeyi ve diğer görevleri gerçekleştirdikten sonra, ayırma işleminin devamebileceğini FALSEbelirten veya işlemin başarısız olması gerektiğini belirten öğesini döndürmelidirTRUE. Bu türdeki basit bir kanca, şimdiye kadar ayrılan bellek miktarını denetleyebilir ve bu miktar küçük bir sınırı aşarsa geri dönebilir FALSE . Uygulama daha sonra normalde yalnızca kullanılabilir bellek düşük olduğunda ortaya çıkabilecek ayırma hataları türüyle karşılaşır. Daha karmaşık kancalar ayırma desenlerini izleyebilir, bellek kullanımını analiz edebilir veya belirli durumlar oluştuğunda rapor verebilir.

Ayırma kancaları ve CRT bellek ayırmaları

Ayırma kancası işlevlerinde önemli bir kısıtlama, blokları açıkça yoksaymaları _CRT_BLOCK gerektiğidir. Bu bloklar, iç belleği ayıran C çalışma zamanı kitaplığı işlevlerine çağrı yaparsa, C çalışma zamanı kitaplığı işlevleri tarafından dahili olarak yapılan bellek ayırmalarıdır. Ayırma kancası işlevinizin başına aşağıdaki kodu ekleyerek blokları yoksayabilirsiniz _CRT_BLOCK :

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

Ayırma kancanız blokları yoksayarsa _CRT_BLOCK , kancanızda çağrılan herhangi bir C çalışma zamanı kitaplığı işlevi programı sonsuz bir döngüde yakalayabilir. Örneğin, printf iç ayırma yapar. Kanca kodunuz öğesini çağırırsa printf, sonuçta elde edilen ayırma kancanızın yeniden çağrılmasına neden olur; bu, yığın taşana kadar yeniden çağrılır printf ve bu şekilde devam eder. Ayırma işlemlerini bildirmeniz _CRT_BLOCK gerekiyorsa, bu kısıtlamayı aşmanın bir yolu, biçimlendirme ve çıkış için C çalışma zamanı işlevleri yerine Windows API işlevlerini kullanmaktır. Windows API'leri C çalışma zamanı kitaplığı yığınını kullanmadığından, ayırma kancanızı sonsuz bir döngüde yakalamaz.

Çalışma zamanı kitaplığı kaynak dosyalarını incelerseniz, varsayılan ayırma kancası işlevinin _CrtDefaultAllocHook (yalnızca döndürür TRUE) kendi debug_heap_hook.cppayrı bir dosyasında bulunduğunu görürsünüz. Uygulamanızın main işlevinden önce yürütülen çalışma zamanı başlangıç kodu tarafından yapılan ayırmalar için bile ayırma kancanızın çağrılmasını istiyorsanız, bu varsayılan işlevi kullanmak _CrtSetAllocHookyerine kendi işlevlerinden biriyle değiştirebilirsiniz.

Kanca işlevlerini raporlama

kullanılarak _CrtSetReportHookyüklenen bir rapor kancası işlevi, her _CrtDbgReport hata ayıklama raporu oluşturulduğunda çağrılır. Raporları belirli ayırma türlerine odaklanmak üzere filtrelemek için diğer özelliklerin dışında bunu kullanabilirsiniz. Bir rapor kancası işlevinin aşağıdaki örneğe benzer bir prototipi olmalıdır:

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

geçirdiğiniz _CrtSetReportHook işaretçi, içinde <crtdbg.h>tanımlandığı gibi türündedir_CRT_REPORT_HOOK:

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

Çalışma zamanı kitaplığı kanca işlevinizi çağırdığında, nRptType bağımsız değişken raporun (_CRT_WARN, veya _CRT_ASSERT) szMsg kategorisini içerir, _CRT_ERRORtam olarak derlenmiş bir rapor ileti dizesine yönelik bir işaretçi içerir ve retVal raporu oluşturduktan sonra normal yürütmeye devam mı _CrtDbgReport yoksa hata ayıklayıcıyı başlatma mı gerektiğini belirtir. (Sıfır retVal değeri yürütmeye devam eder, 1 değeri hata ayıklayıcısını başlatır.)

Kanca söz konusu iletiyi tamamen ele alırsa, başka raporlama gerekmemesi için döndürmelidir TRUE. döndürürse FALSE, _CrtDbgReport iletiyi normal şekilde bildirir.

Bu bölümde

  • Öbek atama işlevleri hata ayıklama sürümleri

    Öbek ayırma işlevlerinin özel Hata Ayıklama sürümlerini açıklar: CRT'nin çağrıları, bunları açıkça çağırmanın avantajları, dönüştürmeyi önleme, istemci bloklarındaki ayrı ayırma türlerini izleme ve tanımlanmama _DEBUGsonuçları.

  • CRT hata ayıklama öbeği ayrıntıları

    Bellek yönetimini ve hata ayıklama yığınını, hata ayıklama yığınındaki blok türlerini, yığın durumu raporlama işlevlerini ve ayırma isteklerini izlemek için hata ayıklama yığınının nasıl kullanılacağını açıklar.

  • CRT kitaplığını kullanarak bellek sızıntılarını bulma

    Hata ayıklayıcısını ve C Çalışma Zamanı Kitaplığı'nı kullanarak bellek sızıntılarını algılama ve yalıtma tekniklerini kapsar.

Ayrıca bkz.