Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
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 DebugBreak
aufgerufen.
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 printf
kann 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
oderfree
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
Erstellen Sie ein CMemoryState-Objekt , und rufen Sie die CMemoryState::Checkpoint-Memberfunktion auf. Dadurch wird die erste Speichermomentaufnahme erstellt.
Nachdem Ihr Programm seine Speicherzuweisungs- und Speicherfreigabe-Vorgänge ausgeführt hat, erstellen Sie ein weiteres
CMemoryState
Objekt und rufen Sie für dieses ObjektCheckpoint
auf. Dadurch wird eine zweite Momentaufnahme der Speicherauslastung angezeigt.Erstellen Sie ein drittes
CMemoryState
-Objekt, rufen Sie die zugehörige CMemoryState::Difference -Memberfunktion auf, und übergeben Sie die ersten beidenCMemoryState
-Objekte als Argumente. Wenn zwischen den beiden Speicherzuständen ein Unterschied besteht, gibt dieDifference
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::Difference
verglichen 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 new
zugeordnet 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 Dump
Dump
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:
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.
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.
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).
Wählen Sie im Projektmappen-Explorer das Projekt aus.
Wählen Sie im Menü "Ansicht " die Option "Eigenschaftenseiten" aus.
Zunächst erstellen Sie eine neue Projektkonfiguration.
Klicken Sie im Dialogfeld <Projekt > Eigenschaftenseiten auf die Schaltfläche Konfigurations-Manager.
Suchen Sie im Dialogfeld Configuration Manager Ihr Projekt im Raster. Wählen Sie in der Spalte "Konfiguration" die Option "Neu...<" aus>.
Geben Sie im Dialogfeld "Neue Projektkonfiguration" im Feld "Projektkonfigurationsname " einen Namen für die neue Konfiguration ein, z. B. "Partielles Debuggen".
Wählen Sie in der Liste " Kopiereinstellungen" die Option "Freigeben" aus.
Klicken Sie auf 'OK ', um das Dialogfeld ' Neue Projektkonfiguration ' zu schließen.
Schließen Sie das Dialogfeld Configuration Manager .
Jetzt legen Sie Optionen für das gesamte Projekt fest.
Wählen Sie im Dialogfeld Eigenschaftenseiten im Ordner "Konfigurationseigenschaften " die Kategorie "Allgemein " aus.
Erweitern Sie im Raster "Projekteinstellungen" die Project-Standardwerte (falls erforderlich).
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".
Ö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".
Ö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.
Klicken Sie auf 'OK ', um die neuen Buildoptionen zu speichern und das Dialogfeld 'Eigenschaftenseiten ' zu schließen.
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.
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:
Öffnen Sie im Projektmappen-Explorer den Ordner " Quelldateien " unter Ihrem Projekt.
Wählen Sie die Datei aus, für die Sie Debuginformationen festlegen möchten.
Wählen Sie im Menü "Ansicht " die Option "Eigenschaftenseiten" aus.
Öffnen Sie im Dialogfeld "Eigenschaftenseiten " unter dem Ordner "Konfigurationseinstellungen " den Ordner "C/C++" , und wählen Sie dann die Kategorie "Allgemein " aus.
Suchen Sie im Eigenschaftenraster das Debuginformationsformat.
Klicken Sie auf die Einstellungen für das Debuginformationsformat , und wählen Sie die gewünschte Option (normalerweise /ZI) für Debuginformationen aus.
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").
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.