Krzysztof Mossakowski
Materiały dla studentów
 

Debugowanie

MFC
Spis treści

Okna dialogowe
klasa CDialog
Informacje ogólne
Makra debugowania
Globalne zmienne i funkcje debugowania
Klasy debugowania

  •  Informacje ogólne

    • MFC zawiera w sobie znaczne ułatwienia śledzenia pracy programu

      • globalne funkcje, makra i zmienne wykorzystywane wyłącznie podczas debugowania

      • własności podstawowej klasy CObject

      • klasy wykorzystywane wyłącznie podczas debugowania

    • Wszystkie udogodnienia debugowania są włączane do programu, gdy jest zadeklarowana stała preprocesora _DEBUG

      • automatycznie generowane przez MFC projekty zawierają dwie konfiguracje kompilacji: Win 32 Debug i Win 32 Release, różnią się one przede wszystkim deklaracją tej stałej

    • Do Visual Studio jest dołączony program Tracer umożliwiający jednoczesne debugowanie wielu aplikacji, bardzo pomocny w przypadku śledzenia programu wykorzystującego DLL

[początek strony]

  •  Makra debugowania

    • ASSERT( booleanExpression )

      • jeśli logiczna wartość parametru makra jest równa FALSE następuje zatrzymanie pracy programu i pokazanie komunikatu z możliwościami: Abort, Retry, Ignore

      • kod w parametrze tego makra zostanie dołączony do programu tylko jeśli jest zadeklarowana stała _DEBUG (czyli nie zostanie w wersji Release)

    • VERIFY( booleanExpression )

      • jeśli jest zadeklarowana stała _DEBUG działa dokładnie jak ASSERT

      • jeśli nie jest, kod w parametrze makra jest wykonywany, ale nie jest sprawdzana wartość logiczna warunku i nie pojawia się komunikat

    • ASSERT_KINDOF( classname, pobject )

      • sprawdzenie przynależności obiektu do klasy

      • to samo co: ASSERT( pobject->IsKindOf( RUNTIME_CLASS( classname )))

      • obiekt musi być z klasy pochodzącej z CObject

    • ASSERT_VALID( pobject )

      • obliczany jest wskaźnik i jeśli nie jest równy NULL, to dla tego obiektu jest wołana metoda CObject::AssertValid

      • obiekt musi być z klasy pochodzącej z CObject

    • TRACE( exp )

      • jeśli flaga afxTraceEnabled jest ustawiona, sformatowany komunikat trafia do wyjścia debugowego

      • zmienna afxTraceFlags daje możliwości sterowania szczegółowością komunikatów debugowych

      • możliwości formatowania komunikatu jak w przypadku funkcji printf

      • jest ograniczenie 512 znaków na jeden komunikat

    • TRACE0, TRACE1, TRACE2, TRACE3

      • odmiany TRACE o określonej liczbie parametrów

    • #define new DEBUG_NEW

      • podczas każdego użycia operatora new zapamiętywana jest nazwa pliku źródłowego i numer linii kodu, gdzie ma miejsce alokacja

      • funkcja CMemoryState::DumpAllObjectsSince() powoduje pokazanie informacji o alokacjach

      • w przypadku niezwalniania pamięci możliwe będzie szybkie znalezienie miejsca alokacji

      • definicja ta musi być umieszczona po ostatniej definicji IMPLEMENT_SERIAL

[początek strony]

  •  Globalne zmienne i funkcje debugowania

    • afxDump

      • predefiniowany obiekt klasy CDumpContext służący zwykle jako parametr metody CObject::Dump

    • afxMemDF

      • zmienna określająca co będzie śledzone przy alokacji i zwalnianiu pamięci

      • allocMemDF | delayFreeMemDF | checkAlwaysMemDF

    • afxTraceEnable

      • włączenie/wyłączenie wypisania komunikatów debugowych przy pomocy makra TRACE

    • afxTraceFlags

      • własności komunikatów debugowych z makra TRACE

    • AfxCheckError( SCODE sc )

      • sprawdzenie, czy w kodzie przekazanym jako parametr wystąpił błąd

    • AfxCheckMemory()

      • sprawdzenie poprawności bloków pamięci alokowanych przy użyciu operatora new 

      • jeśli jest zadeklarowana stała DEBUG_NEW zostaną wypisane dokonane alokacje

    • AfxDump( const CObject *pOb )

      • wywołanie metody CObject::Dump dla obiektu

      • obiekt musi być z klasy pochodzącej z CObject

    • AfxDumpStack( DWORD dwTarget )

      • wypisuje zawartość stosu programu jako TRACE, OutputDebugString lub do clipboard

    • AfxEnableMemoryTracking( BOOL bTrack )

      • włączenie/wyłączenie śledzenia pamięci (domyślnie włączone)

    • AfxIsMemoryBlock( const void *p, UINT nBytes, LONG *plRequestNumber )

      • sprawdzenie, czy wskazany blok pamięci jest aktualnie zaalokowany przez diagnostyczną wersję operatora new i sprawdza poprawność rozmiaru

    • AfxIsValidAddress( const void *p, UINT nBytes, BOOL bReadWrite )

      • sprawdzenie adresu pamięci

    • AfxIsValidString( LPCSTR lpsz, int nLength )

      • sprawdzenie poprawności ciągu znaków

    • AfxSetAllocHook( AFX_ALLOC_HOOK pfnAllocHook )

      • ustawienie funkcji, która będzie wołana przed zaalokowaniem pamięci

    • AfxDoForAllClasses

      • wykonanie metody dla wszystkich zdefiniowanych z DECLARE_SERIAL klas

    • AfxDoForAllObjects

      • wykonanie metody dla wszystkich obiektów zaalokowanych przez operator new

[początek strony]

  •  Klasy debugowania

    • CDumpContext
      • obsługuje diagnostyczne wyjście

      • w aplikacjach MFC jest utworzony obiekt afxDump tej klasy, w większości zastosowań jest on całkowicie wystarczający

      • wyjście jest wysyłane do funcji API OutputDebugString

    • CMemoryState

      • pomaga wykryć niezwalnianie pamięci (memory leaks), ale tylko w przypadku użycia operatorów new i delete

      • sposób użycia:
        - na początku sprawdzanego kodu utworzyć obiekt CMemoryState i wywołać CMemoryState::Checkpoint
        - na końcu sprawdzanego kodu utworzyć drugi obiekt CMemoryState i wywołać tą samą metodę
        - utworzyć trzeci obiekt tej klasy i wywołać CMemoryState::Difference

[początek strony]