Freigeben über


MFC-Debuggingtechniken

Wenn Sie ein MFC-Programm debuggen, sind diese Debugtechniken möglicherweise hilfreich.

AfxDebugBreak

MFC bietet eine AfxDebugBreak-Funktion speziell für fest codierte Haltepunkte im Quellcode an.

AfxDebugBreak( );

Auf Intel-Plattformen generiert AfxDebugBreak den folgenden Code, der zu Unterbrechungen im Quellcode und nicht im Kernelcode führt:

_asm int 3

Auf anderen Plattformen wird durch AfxDebugBreak lediglich DebugBreakaufgerufen.

Achten Sie darauf, die AfxDebugBreak -Anweisungen vor dem Erstellen eines Releasebuilds zu entfernen oder sie in #ifdef _DEBUG einzuschließen.

Das TRACE-Makro

Um Nachrichten aus Ihrem Programm im Debuggerausgabefenster anzuzeigen, können Sie das ATLTRACE-Makro oder das MFC TRACE-Makro verwenden. Wie Assertions sind die Tracing-Makros nur in der Debug-Version Ihres Programms aktiv und verschwinden, wenn sie in der Release-Version kompiliert werden.

Die folgenden Beispiele zeigen einige der Möglichkeiten, wie Sie das TRACE-Makro verwenden können. Wie printfkann das TRACE-Makro eine Reihe von Argumenten verarbeiten.

int x = 1;
int y = 16;
float z = 32.0;
TRACE( "This is a TRACE statement\n" );

TRACE( "The value of x is %d\n", x );

TRACE( "x = %d and y = %d\n", x, y );

TRACE( "x = %d and y = %x and z = %f\n", x, y, z );

Das TRACE-Makro behandelt sowohl char*- als auch wchar_t*-Parameter entsprechend. Die folgenden Beispiele veranschaulichen die Verwendung des TRACE-Makros zusammen mit verschiedenen Typen von Zeichenfolgenparametern.

TRACE( "This is a test of the TRACE macro that uses an ANSI string: %s %d\n", "The number is:", 2);

TRACE( L"This is a test of the TRACE macro that uses a UNICODE string: %s %d\n", L"The number is:", 2);

TRACE( _T("This is a test of the TRACE macro that uses a TCHAR string: %s %d\n"), _T("The number is:"), 2);

Weitere Informationen zum TRACE-Makro finden Sie unter Diagnosedienste.

Erkennen von Speicherlecks in MFC

MFC stellt Klassen und Funktionen bereit, mit deren Hilfe Speicherbereiche ermittelt werden können, die belegt, jedoch nicht wieder freigegeben werden.

Nachverfolgen von Speicherzuweisungen

In MFC können Sie das Makro DEBUG_NEW anstelle des neuen Operators verwenden, um Speicherverluste zu finden. In der Debugversion des Programms werden durch DEBUG_NEW die Dateinamen und Zeilennummern jedes von ihm reservierten Objekts nachverfolgt. Wenn Sie eine Releaseversion des Programms kompilieren, wird DEBUG_NEW in eine einfache new -Operation aufgelöst, ohne dass Dateinamen und Zeilennummern aufgelöst werden. Daher zahlen Sie keine Geschwindigkeitsstrafe in der Release-Version Ihres Programms.

Wenn Sie nicht das gesamte Programm umschreiben möchten, um DEBUG_NEW anstelle von newzu verwenden, können Sie dieses Makro in den Quellcodedateien definieren:

#define new DEBUG_NEW

Wenn Sie ein Objektabbild ausführen, zeigt jedes zugeordnete DEBUG_NEW Objekt die Datei- und Zeilennummer, an der es zugeordnet wurde, sodass Sie die Quellen von Speicherverlusten identifizieren können.

Die Debugversion des MFC-Frameworks verwendet DEBUG_NEW automatisch, Ihr Code jedoch nicht. Wenn Sie die Vorteile von DEBUG_NEW nutzen möchten, müssen Sie DEBUG_NEW explizit verwenden oder #define new wie oben gezeigt.

Aktivieren der Speicherdiagnose

Bevor Sie die Speicherdiagnoseeinrichtungen verwenden können, müssen Sie die Diagnoseablaufverfolgung aktivieren.

So aktivieren oder deaktivieren Sie die Speicherdiagnose

  • Rufen Sie die globale Funktion AfxEnableMemoryTracking auf, um den Diagnosespeicher-Allocator zu aktivieren oder zu deaktivieren. Da die Speicherdiagnose in der Debugbibliothek standardmäßig aktiviert ist, verwenden Sie diese Funktion in der Regel, um sie vorübergehend zu deaktivieren, wodurch die Programmausführungsgeschwindigkeit erhöht und die Diagnoseausgabe reduziert wird.

    So wählen Sie bestimmte Speicherdiagnosefeatures mit afxMemDF aus

  • Wenn Sie genauere Kontrolle über die Speicherdiagnosefeatures wünschen, können Sie einzelne Speicherdiagnosefeatures selektiv aktivieren und deaktivieren, indem Sie den Wert der globalen MFC-Variablen afxMemDF festlegen. Diese Variable kann die folgenden Werte aufweisen, wie durch den aufgezählten Typ afxMemDF angegeben.

    Wert BESCHREIBUNG
    allocMemDF Aktivieren Sie den Diagnosespeicher-Allocator (Standardeinstellung).
    delayFreeMemDF Verzögern des Freigebens von Arbeitsspeicher beim Aufrufen delete oder free bis zum Beenden des Programms. Dies führt dazu, dass Ihr Programm die maximal mögliche Arbeitsspeichermenge zuweist.
    checkAlwaysMemDF Rufen Sie AfxCheckMemory jedes Mal auf, wenn Arbeitsspeicher zugewiesen oder freigegeben wird.

    Diese Werte können in Kombination verwendet werden, indem sie einen logischen ODER-Vorgang ausführen, wie hier gezeigt:

    afxMemDF = allocMemDF | delayFreeMemDF | checkAlwaysMemDF;
    

Aufzeichnen von Speichermomentaufnahmen

  1. Erstellen Sie ein CMemoryState-Objekt , und rufen Sie die CMemoryState::Checkpoint-Memberfunktion auf. Dadurch wird die erste Speichermomentaufnahme erstellt.

  2. Nachdem Ihr Programm seine Speicherzuweisungs- und Speicherfreigabe-Vorgänge ausgeführt hat, erstellen Sie ein weiteres CMemoryState Objekt und rufen Sie für dieses Objekt Checkpoint auf. Dadurch wird eine zweite Momentaufnahme der Speicherauslastung angezeigt.

  3. Erstellen Sie ein drittes CMemoryState -Objekt, rufen Sie die zugehörige CMemoryState::Difference -Memberfunktion auf, und übergeben Sie die ersten beiden CMemoryState -Objekte als Argumente. Wenn zwischen den beiden Speicherzuständen ein Unterschied besteht, gibt die Difference Funktion einen Wert ungleich Null zurück. Dies weist darauf hin, dass einige Speicherblöcke nicht umgestellt wurden.

    In diesem Beispiel wird gezeigt, wie der Code aussieht:

    // Declare the variables needed
    #ifdef _DEBUG
        CMemoryState oldMemState, newMemState, diffMemState;
        oldMemState.Checkpoint();
    #endif
    
        // Do your memory allocations and deallocations.
        CString s("This is a frame variable");
        // The next object is a heap object.
        CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
    
    #ifdef _DEBUG
        newMemState.Checkpoint();
        if( diffMemState.Difference( oldMemState, newMemState ) )
        {
            TRACE( "Memory leaked!\n" );
        }
    #endif
    

    Beachten Sie, dass die Speicherüberprüfungsanweisungen durch #ifdef _DEBUG/#endif Blöcke klammert werden, sodass sie nur in Debugversionen Ihres Programms kompiliert werden.

    Da Sie nun wissen, dass ein Speicherverlust auftritt, können Sie eine andere Memberfunktion namens CMemoryState::DumpStatistics verwenden, um die Stelle zu lokalisieren.

Anzeigen von Speicherstatistiken

Durch die CMemoryState::Difference -Funktion werden die beiden Speicherzustandsobjekte verglichen und alle Objekte ermittelt, die zwischen dem Anfangs- und dem Endzustand nicht vom Heap freigegeben wurden. Nachdem Sie Speichermomentaufnahmen aufgezeichnet und diese mithilfe von CMemoryState::Differenceverglichen haben, können Sie CMemoryState::DumpStatistics aufrufen, um Informationen über die nicht freigegebenen Objekte zu erhalten.

Betrachten Sie das folgenden Beispiel:

if( diffMemState.Difference( oldMemState, newMemState ) )
{
    TRACE( "Memory leaked!\n" );
    diffMemState.DumpStatistics();
}

Ein Beispieldump dieses Codes sieht z. B. wie folgt aus:

0 bytes in 0 Free Blocks
22 bytes in 1 Object Blocks
45 bytes in 4 Non-Object Blocks
Largest number used: 67 bytes
Total allocations: 67 bytes

Freie Blöcke sind Blöcke, deren Freigabe verzögert wird, wenn afxMemDF auf delayFreeMemDF gesetzt wurde.

Gewöhnliche Objektblöcke, die in der zweiten Zeile angezeigt werden, bleiben auf dem Heap zugeordnet.

Nicht-Objektblöcke umfassen Arrays und Strukturen, die newzugeordnet sind. In diesem Fall wurden vier Elemente, die kein Objekt darstellen, auf dem Heap reserviert, jedoch nicht freigegeben.

Largest number used gibt den vom Programm verwendeten maximalen Arbeitsspeicher zu jedem Zeitpunkt an.

Total allocations gibt die Gesamtmenge des vom Programm verwendeten Arbeitsspeichers an.

Nachverfolgen von Objektabbildern

In einem MFC-Programm kann CMemoryState::DumpAllObjectsSince verwendet werden, um eine Beschreibung aller Objekte auf dem Heap zu sichern, die nicht freigegeben wurden. DumpAllObjectsSince sichert alle seit dem letzten CMemoryState::Checkpointaufgerufen. Wenn kein Checkpoint Aufruf erfolgt ist, löscht DumpAllObjectsSince alle Objekte und Nichtobjekte, die sich derzeit im Arbeitsspeicher befinden.

Hinweis

Bevor MFC-Objektdumps erstellt werden können, muss die Diagnosenachverfolgungaktiviert werden.

Hinweis

MFC gibt automatisch alle undichten Objekte aus, wenn das Programm beendet wird, sodass Sie an diesem Punkt keinen Code zum Ausgeben von Objekten erstellen müssen.

Durch den folgenden Code werden alle Objekte auf Speicherverluste getestet, indem die beiden Speicherzustände verglichen und bei Auftreten von Verlusten alle Objekte gesichert werden.

if( diffMemState.Difference( oldMemState, newMemState ) )
{
    TRACE( "Memory leaked!\n" );
    diffMemState.DumpAllObjectsSince();
}

Im Folgenden der Inhalt des Dumps:

Dumping objects ->

{5} strcore.cpp(80) : non-object block at $00A7521A, 9 bytes long
{4} strcore.cpp(80) : non-object block at $00A751F8, 5 bytes long
{3} strcore.cpp(80) : non-object block at $00A751D6, 6 bytes long
{2} a CPerson at $51A4

Last Name: Smith
First Name: Alan
Phone #: 581-0215

{1} strcore.cpp(80) : non-object block at $00A7516E, 25 bytes long

Die Zahlen in geschweiften Klammern am Anfang der meisten Zeilen geben die Reihenfolge an, in der die Objekte zugeordnet wurden. Das zuletzt zugewiesene Objekt hat die höchste Zahl und erscheint oben im Dump.

Um die maximale Informationsmenge aus einem Objektdump abzurufen, können Sie die Dump-Memberfunktion einer beliebigen CObject-abgeleiteten Objekts überschreiben, um den Objektdump anzupassen.

Sie können einen Haltepunkt für eine bestimmte Speicherzuordnung festlegen, indem Sie die globale Variable _afxBreakAlloc auf die in den geschweiften Klammern angezeigte Zahl festlegen. Wenn Sie das Programm erneut ausführen, wird die Ausführung durch den Debugger abgebrochen, wenn diese Zuordnung stattfindet. Anschließend können Sie sich den Aufrufstapel ansehen, um zu sehen, wie Ihr Programm zu diesem Zeitpunkt gelangt ist.

Die C-Laufzeitbibliothek hat eine ähnliche Funktion, _CrtSetBreakAlloc, die Sie für C-Laufzeitzuweisungen verwenden können.

Interpretation von Speicherabbildern

Betrachten Sie diesen Objektdump genauer.

{5} strcore.cpp(80) : non-object block at $00A7521A, 9 bytes long
{4} strcore.cpp(80) : non-object block at $00A751F8, 5 bytes long
{3} strcore.cpp(80) : non-object block at $00A751D6, 6 bytes long
{2} a CPerson at $51A4

Last Name: Smith
First Name: Alan
Phone #: 581-0215

{1} strcore.cpp(80) : non-object block at $00A7516E, 25 bytes long

Das Programm, das dieses Dump generiert hat, hatte nur zwei explizite Zuordnungen – eine auf dem Stapel und eine auf dem Heap:

// Do your memory allocations and deallocations.
CString s("This is a frame variable");
// The next object is a heap object.
CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );

Der CPerson-Konstruktor verwendet drei Argumente, die Zeiger auf char sind, die zum Initialisieren der CString-Membervariablen verwendet werden. Im Speicherabbild können Sie das CPerson Objekt zusammen mit drei Nichtobjektblöcken (3, 4 und 5) sehen. Diese enthalten die Zeichen für die CString Membervariablen und werden nicht gelöscht, wenn der CPerson Objekt destruktor aufgerufen wird.

Blocknummer 2 ist das CPerson Objekt selbst. $51A4 stellt die Adresse des Blocks dar und folgt dem Inhalt des Objekts, das von CPerson::Dump beim Aufruf von DumpAllObjectsSince ausgegeben wurde.

Sie können erraten, dass die Blocknummer 1 der CString Framevariable aufgrund der Sequenznummer und -größe zugeordnet ist, die der Anzahl der Zeichen in der Framevariable CString entspricht. Reservierungen für Framevariablen werden automatisch freigegeben, wenn die Framevariable den Gültigkeitsbereich verlässt.

Framevariablen

Im Allgemeinen brauchen Sie sich um Heapobjekte, die mit Framevariablen verknüpft sind, nicht zu kümmern, da sie automatisch freigegeben werden, wenn die Framevariable den Gültigkeitsbereich verlässt. Um übersichtliche Dumps für die Speicherdiagnose zu erhalten, sollten Sie die Checkpoint -Aufrufe so positionieren, dass sie nicht im Gültigkeitsbereich von Framevariablen liegen. Platzieren Sie z. B. Bereichsklammern um den vorherigen Zuordnungscode, wie hier gezeigt:

oldMemState.Checkpoint();
{
    // Do your memory allocations and deallocations ...
    CString s("This is a frame variable");
    // The next object is a heap object.
    CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
}
newMemState.Checkpoint();

Mit diesen Klammern sieht der Speicherdump für dieses Beispiel wie folgt aus:

Dumping objects ->

{5} strcore.cpp(80) : non-object block at $00A7521A, 9 bytes long
{4} strcore.cpp(80) : non-object block at $00A751F8, 5 bytes long
{3} strcore.cpp(80) : non-object block at $00A751D6, 6 bytes long
{2} a CPerson at $51A4

Last Name: Smith
First Name: Alan
Phone #: 581-0215

Nicht-Objektreservierungen

Beachten Sie, dass einige Belegungen sich auf Objekte (z. B. CPerson) und andere auf „Nicht-Objekte“ beziehen. „Nicht-Objekt-Speicherbelegungen“ sind Speicherbelegungen für Objekte, die nicht von CObject abgeleitet wurden, oder Speicherbelegungen primitiver C-Typen wie char, int oder long. Wenn die von CObject abgeleitete Klasse zusätzlichen Platz zuweist, z. B. für interne Puffer, werden diese Objekte sowohl Objekt- als auch Nichtobjektzuordnungen anzeigen.

Verhindern von Speicherlecks

Beachten Sie im obigen Code, dass der speicherblock, der der CString Framevariable zugeordnet ist, automatisch zugeordnet wurde und nicht als Speicherverlust angezeigt wird. Die automatische Freigabe aufgrund von Gültigkeitsbereichsregeln verhindert normalerweise Speicherverluste in Zusammenhang mit Framevariablen.

Bei Objekten, die dem Heap zugeordnet sind, müssen Sie das Objekt jedoch explizit löschen, um einen Speicherverlust zu verhindern. Um den letzten Speicherverlust im vorherigen Beispiel zu bereinigen, löschen Sie das CPerson für den Heap zugewiesene Objekt wie folgt:

{
    // Do your memory allocations and deallocations.
    CString s("This is a frame variable");
    // The next object is a heap object.
    CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
    delete p;
}

Anpassen von Objektdumps

Wenn Sie eine Klasse von CObject ableiten, können Sie die Dump Memberfunktion überschreiben, um zusätzliche Informationen bereitzustellen, wenn Sie DumpAllObjectsSince verwenden, um Objekte im Ausgabefenster auszugeben.

Die Dump Funktion schreibt eine textbezogene Darstellung der Membervariablen des Objekts in einen Dumpkontext (CDumpContext). Der Dumpkontext ähnelt einem E/A-Datenstrom. Mithilfe des Anfügeoperators (<<) können Sie Daten an einen CDumpContext aufgerufen.

Wenn Sie die Dump Funktion außer Kraft setzen, sollten Sie zuerst die Basisklassenversion Dump aufrufen, um den Inhalt des Basisklassenobjekts abzubilden. Geben Sie dann eine Textbeschreibung und einen Wert für jede Membervariable ihrer abgeleiteten Klasse aus.

Die Deklaration der Dump Funktion sieht wie folgt aus:

class CPerson : public CObject
{
public:
#ifdef _DEBUG
    virtual void Dump( CDumpContext& dc ) const;
#endif

    CString m_firstName;
    CString m_lastName;
    // And so on...
};

Da objektdumping nur sinnvoll ist, wenn Sie Ihr Programm debuggen, wird die Deklaration der Dump Funktion mit einem #ifdef _DEBUG/#endif-Block in eckige Klammern gesetzt.

Im folgenden Beispiel ruft die Funktion zunächst die DumpDump Funktion für ihre Basisklasse auf. Dann wird eine Kurzbeschreibung jeder Membervariablen sowie der zugehörige Wert in den Diagnosestream geschrieben.

#ifdef _DEBUG
void CPerson::Dump( CDumpContext& dc ) const
{
    // Call the base class function first.
    CObject::Dump( dc );

    // Now do the stuff for our specific class.
    dc << "last name: " << m_lastName << "\n"
        << "first name: " << m_firstName << "\n";
}
#endif

Sie müssen ein CDumpContext -Argument angeben, um festzulegen, wo der Dump ausgegeben wird. Die Debugversion von MFC stellt ein vordefiniertes CDumpContext Objekt afxDump bereit, das die Ausgabe an den Debugger sendet.

CPerson* pMyPerson = new CPerson;
// Set some fields of the CPerson object.
//...
// Now dump the contents.
#ifdef _DEBUG
pMyPerson->Dump( afxDump );
#endif

Verringern der Größe eines MFC-Debugbuilds

Die Debuginformationen für eine große MFC-Anwendung können viel Speicherplatz belegen. Sie können eines der folgenden Verfahren verwenden, um die Größe zu verringern:

  1. Erstellen Sie die MFC-Bibliotheken mithilfe der Option /Z7, /Zi, /ZI (Debug Information Format) anstelle von /Z7 neu. Diese Optionen erstellen eine einzelne Programmdatenbankdatei (PDB), die Debuginformationen für die gesamte Bibliothek enthält, wodurch Redundanz reduziert und Speicherplatz gespart wird.

  2. Erstellen Sie die MFC-Bibliotheken ohne Debuginformationen (ohne die Option /Z7, /Zi, /Zi (Debuginformationsformat)). In diesem Fall wird das Fehlen von Debuginformationen verhindern, dass Sie die meisten Debugger-Einrichtungen im MFC-Bibliothekscode verwenden, aber da die MFC-Bibliotheken bereits gründlich gedebuggt sind, ist dies möglicherweise kein Problem.

  3. Erstellen Sie Ihre eigene Anwendung mit Debuginformationen für ausgewählte Module nur wie unten beschrieben.

Erstellen einer MFC-App mit Debuginformationen für ausgewählte Module

Das Erstellen ausgewählter Module mit den MFC-Debugbibliotheken ermöglicht die schrittweise Ausführung der Module sowie die Verwendung weiterer Debugfunktionen. Mit diesem Verfahren werden sowohl die Debug- als auch die Releasekonfigurationen des Projekts verwendet, sodass die in den folgenden Schritten beschriebenen Änderungen erforderlich sind (und auch eine "Neuerstellung aller" erforderlich ist, wenn ein vollständiger Release-Build erforderlich ist).

  1. Wählen Sie im Projektmappen-Explorer das Projekt aus.

  2. Wählen Sie im Menü "Ansicht " die Option "Eigenschaftenseiten" aus.

  3. Zunächst erstellen Sie eine neue Projektkonfiguration.

    1. Klicken Sie im Dialogfeld <Projekt > Eigenschaftenseiten auf die Schaltfläche Konfigurations-Manager.

    2. Suchen Sie im Dialogfeld Configuration Manager Ihr Projekt im Raster. Wählen Sie in der Spalte "Konfiguration" die Option "Neu...<" aus>.

    3. Geben Sie im Dialogfeld "Neue Projektkonfiguration" im Feld "Projektkonfigurationsname " einen Namen für die neue Konfiguration ein, z. B. "Partielles Debuggen".

    4. Wählen Sie in der Liste " Kopiereinstellungen" die Option "Freigeben" aus.

    5. Klicken Sie auf 'OK ', um das Dialogfeld ' Neue Projektkonfiguration ' zu schließen.

    6. Schließen Sie das Dialogfeld Configuration Manager .

  4. Jetzt legen Sie Optionen für das gesamte Projekt fest.

    1. Wählen Sie im Dialogfeld Eigenschaftenseiten im Ordner "Konfigurationseigenschaften " die Kategorie "Allgemein " aus.

    2. Erweitern Sie im Raster "Projekteinstellungen" die Project-Standardwerte (falls erforderlich).

    3. Suchen Sie unter Projektstandardsdie Option Verwendung von MFC. Die aktuelle Einstellung wird in der rechten Spalte des Rasters angezeigt. Klicken Sie auf die aktuelle Einstellung, und ändern Sie sie in "MFC in einer statischen Bibliothek verwenden".

    4. Öffnen Sie im linken Bereich des Dialogfelds "Eigenschaftenseiten " den Ordner "C/C++" , und wählen Sie "Preprocessor" aus. Suchen Sie im Eigenschaftenraster nach Präprozessordefinitionen , und ersetzen Sie "NDEBUG" durch "_DEBUG".

    5. Öffnen Sie im linken Bereich des Dialogfelds "Eigenschaftenseiten " den Ordner "Linker ", und wählen Sie die Eingabekategorie aus. Suchen Sie im Eigenschaftenraster nach weiteren Abhängigkeiten. Geben Sie in der Einstellung "Zusätzliche Abhängigkeiten" "NAFXCWD.LIB" und "LIBCMT." ein.

    6. Klicken Sie auf 'OK ', um die neuen Buildoptionen zu speichern und das Dialogfeld 'Eigenschaftenseiten ' zu schließen.

  5. Wählen Sie im Menü " Erstellen " die Option "Neu erstellen" aus. Dadurch werden alle Debuginformationen aus Ihren Modulen entfernt, sich jedoch nicht auf die MFC-Bibliothek auswirken.

  6. Jetzt müssen Sie Debuginformationen zurück zu ausgewählten Modulen in Ihrer Anwendung hinzufügen. Denken Sie daran, dass Sie Haltepunkte festlegen und andere Debuggerfunktionen nur in Modulen ausführen können, die Sie mit Debuginformationen kompiliert haben. Führen Sie für jede Projektdatei, in die Sie Debuginformationen einschließen möchten, die folgenden Schritte aus:

    1. Öffnen Sie im Projektmappen-Explorer den Ordner " Quelldateien " unter Ihrem Projekt.

    2. Wählen Sie die Datei aus, für die Sie Debuginformationen festlegen möchten.

    3. Wählen Sie im Menü "Ansicht " die Option "Eigenschaftenseiten" aus.

    4. Öffnen Sie im Dialogfeld "Eigenschaftenseiten " unter dem Ordner "Konfigurationseinstellungen " den Ordner "C/C++" , und wählen Sie dann die Kategorie "Allgemein " aus.

    5. Suchen Sie im Eigenschaftenraster das Debuginformationsformat.

    6. Klicken Sie auf die Einstellungen für das Debuginformationsformat , und wählen Sie die gewünschte Option (normalerweise /ZI) für Debuginformationen aus.

    7. Wenn Sie eine vom Anwendungs-Assistenten generierte Anwendung verwenden oder über vorkompilierte Header verfügen, müssen Sie die vorkompilierten Header deaktivieren oder neu kompilieren, bevor Sie die anderen Module kompilieren. Andernfalls erhalten Sie die Warnung C4650 und fehlermeldung C2855. Sie können vorkompilierte Kopfzeilen deaktivieren, indem Sie die Einstellung "Vorkompilierte Kopfzeilen erstellen/verwenden" im <Dialogfeld "Projekteigenschaften>" ändern (Konfigurationseigenschaftenordner, C/C++-Unterordner, Kategorie "Vorkompilierte Kopfzeilen").

  7. Wählen Sie im Menü " Erstellen " die Option "Erstellen " aus, um Projektdateien neu zu erstellen, die veraltet sind.

    Als Alternative zu der in diesem Thema beschriebenen Technik können Sie eine externe Makefile verwenden, um einzelne Optionen für jede Datei zu definieren. In diesem Fall müssen Sie zum Verknüpfen mit den MFC-Debugbibliotheken das _DEBUG Flag für jedes Modul definieren. Wenn Sie MFC-Releasebibliotheken verwenden möchten, müssen Sie NDEBUG definieren. Weitere Informationen zum Schreiben externer Makefiles finden Sie in der NMAKE-Referenz.