Heim >Backend-Entwicklung >C#.Net-Tutorial >Erkennung von Speicherlecks in C++
Zuerst müssen wir wissen, ob das Programm einen Speicherverlust aufweist, und dann herausfinden, welche Codezeile den Speicherverlust aufweist, damit wir ihn beheben können.
Der einfachste Weg ist natürlich die Verwendung professioneller Erkennungstools wie BoundsCheck, das bekannt und sehr leistungsfähig ist. Ich glaube, dass niemand, der C++ entwickelt, darauf verzichten kann. Darüber hinaus
Zuerst müssen wir wissen, ob das Programm einen Speicherverlust aufweist, und dann ermitteln, welche Codezeile den Speicherverlust aufweist, damit wir ihn beheben können.
Der einfachste Weg ist natürlich die Verwendung professioneller Erkennungstools wie BoundsCheck, das bekannt und sehr leistungsfähig ist. Ich glaube, dass niemand, der C++ entwickelt, darauf verzichten kann. Darüber hinaus verwenden Sie keine Tools, sondern implementieren die Überwachung von Speicherlecks selbst, die in die folgenden zwei Situationen unterteilt werden kann:
1. Erkennen von Speicherlecks in MFC
Wenn Sie Sie verwenden ein MFC-Programm. Wenn ja, ist es ganz einfach. Standardmäßig gibt es eine Funktion zur Erkennung von Speicherlecks.
Wir haben VS2005 zum Generieren eines MFC-Dialogfeldprogramms verwendet und festgestellt, dass es Speicherlecks automatisch erkennen kann. Nach sorgfältiger Beobachtung haben wir festgestellt, dass dies in jeder CPP-Datei der Fall ist sind der folgende Code:
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
DEBUG_NEW Dieses Makro ist in der Datei afx.h definiert, was uns hilft, Speicherlecks zu lokalisieren.
Wenn der Speicher nicht gelöscht wird, nachdem Speicher in der CPP-Datei mit dem obigen Code zugewiesen wurde, zeigt das Ausgabefenster von VisualStudio beim Stoppen des Programms die folgenden Informationen an:
Erkannte Speicherlecks!
Objekte sichern ->
d:codemfctestmfctest.cpp(80): {157} normaler Block bei 0x003AF170, 4 Bytes lang.
Daten: < > .
#include "stdafx.h"
#include
int _tmain(int argc, _TCHAR* argv[])
{
int* p = new int;
_CrtDumpMemoryLeaks;
return 0;
}
Erkannte Speicherlecks!
Objekte werden ausgegeben ->
{112} normaler Block bei 0x003AA770, 4 Bytes lang.
Daten: < > ; 00 00 00 00
Objekt-Dump abgeschlossen.
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
int _tmain(int argc, _TCHAR* argv[])
{
int* p = new int;
_CrtDumpMemoryLeaks;
return 0;
}
Objekte ausgeben ->
d:codeconsoletestconsoletest.cpp(21): {112} Client-Block bei 0x003A38B0, Subtyp 0, 4 Bytes lang.
Daten: < 00 00 00
Objekt-Dump abgeschlossen.
{
int* p = new int;
_CrtDumpMemoryLeaks;
delete p ;
return 0;
}
#include "stdafx.h"
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
# _CRTDBG_MAP_ALLOC
#include
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
class Test
{
public:
Test define { _p = new int;🎜>~Test { delete _p;
};
int _tmain(int argc, _TCHAR* argv[])
{
int* p = new int;
delete p;
Test t;
_CrtDumpMemoryLeaks;
return 0;
}
Sie können sehen, dass der Destruktor beendet wird, wenn das Programm ausgeführt wird Exits Es wird nur aufgerufen, wenn es aufgerufen wird. Es liegt offensichtlich kein Speicherverlust vor, aber diese Schreibweise wird trotzdem gemeldet.
Informationen zur Verbesserung finden Sie in Version 3 der Speicherleckerkennung:
#include "stdafx.h"
#ifdef _DEBUG#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
# endif
class Test
{
public:
Test { _p = new int; }
~Test { delete _p; }
int* _p;
};
int _tmain(int argc, _TCHAR* argv[])
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
int* p = new int;
delete p;
Test t;
return 0;
}
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); Diese Anweisung ruft automatisch _CrtDumpMemoryLeaks auf, wenn das Programm beendet wird. _CRTDBG_ALLOC_MEM_DF und _CRTDBG_LEAK_CHECK_DF müssen gleichzeitig festgelegt werden.
Auf diese Weise hat diese Version den gleichen Effekt wie MFC erzielt, aber ich denke, das reicht nicht aus, da wir nur Informationen im Ausgabefenster ausgeben, was ist für Entwickler sehr wichtig. Die Erinnerung ist noch nicht offensichtlich und wird oft übersehen. Darüber hinaus ist es schwierig, es zu reparieren, selbst wenn viele Leute es entdecken, und beeinträchtigt die externe Leistung des Programms nicht ernsthaft. Wie können Entwickler Speicherlecks proaktiv beheben? Ich erinnere mich, dass ich einmal mit jemandem zusammengearbeitet habe, um ein Programm zu schreiben. Meine Funktionsparameter hatten Anforderungen und durften nicht leer sein, aber andere hatten immer keine andere Wahl, als die Funktionsparameter am Anfang der Funktion zu überprüfen und zu bestätigen Auf diese Weise tauchte beim Ausführen des Programms immer wieder die Behauptung auf, was das Debuggen des Programms sehr anstrengend machte. Schließlich waren andere Programmierer verärgert, sodass sie das Problem behoben und die Parameter korrekt eingegeben hatten. Ich denke also, wenn wir wollen, dass Programmierer die Initiative ergreifen, etwas zu tun, müssen wir ihnen zunächst das Gefühl geben, dass dies ihre Belastung verringern und ihre Arbeit erleichtern kann. Haha, machen wir das Gleiche. Wenn das Programm beendet wird und ein Speicherverlust erkannt wird, wird das Programm Sie dazu auffordern.
Siehe Version 4 zur Erkennung von Speicherlecks:
#include "stdafx.h"
#include#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new ( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include
#ifdef _DEBUG
# new DEBUG_CLIENTBLOCK
#endif
void Exit
{
int i = _CrtDumpMemoryLeaks;
assert( i == 0);
}
int _tmain(int argc, _TCHAR define * argv[])
{
atexit(Exit);
int* p = new int;
return 0;
}
Diese Version wird ausgeführt, wenn Das Programm wird beendet. Wenn ein Speicherverlust vorliegt, wird ein Eingabeaufforderungsdialogfeld angezeigt.
atexit(Exit) legt die Exit-Funktion fest, die beim Beenden des Programms ausgeführt werden soll. Wenn in der Exit-Funktion ein Speicherverlust vorliegt, gibt _CrtDumpMemoryLeaks einen Wert ungleich 0 zurück und dieser wird bestätigt.
Diese Version ist einsatzbereit. Aber wir können noch einige Verbesserungen vornehmen, denn wenn wir wirklich alle Speicherlecks im Code genau erkennen wollen, müssen wir das #define... im Code mit new in alle Dateien kopieren. Es ist unmöglich, so viel Code für jede Datei zu kopieren, also können wir ihn extrahieren und in eine Datei einfügen. Der Inhalt der Datei lautet wie folgt:
#pragma Once
#ifdef _DEBUG#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
# einschließen < ;stdlib. h>
#include
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
Dann fügen Sie KDetectMemoryLeak.h in die gemeinsame Datei ein des Projekts. Beispielsweise wird ein mit VS erstelltes Projekt es in stdafx.h einschließen. Oder ich habe selbst eine Common.h-Datei erstellt, die allgemeinen Code enthält, der von praktisch allen Dateien verwendet wird.