Ich möchte Speicherverluste meines C ++ Programms in Windows erkennen. Ich lese die Dokumentation auch auf MSDN über mermoy Lecksuche und ich habe auch angefangen, Visual Leak Detector zu verwenden.
Ich habe Zweifel an der Meldung der Lecks. Ich erwarte einen Dateinamen mit einer Zeilennummer, aber mir wird immer der folgende Text gemeldet. Es enthält alle Komponenten einer Leckbeschreibung (Blocktyp, Speicheradresse, Daten usw.). außer dem Dateinamen und der Zeilennummer.
Wenn es ein echtes Leck ist? Wenn ja, wissen Sie, warum die Datei / Zeile nicht gemeldet wird? In der Zwischenzeit schaue ich auch auf diese URL
Danke
%Vor%Ich habe verschiedene Methoden untersucht, um Speicherlecks zu verfolgen. Sie alle haben ihre Vorteile, aber auch ihre Nachteile.
Um ihre Vor- und Nachteile zu verstehen, müssen wir die verschiedenen Mechanismen und Anforderungen verstehen:
Wie werden neu, löschen, malloc und frei abgefangen? Einige Tools verwenden #define, um neu zu definieren, delete, malloc und free, aber dies hängt von der richtigen Reihenfolge der Include-Dateien ab und kann Probleme verursachen, wenn eine Klasse z. eine Methode namens free (wie in Qt). Der Präprozessor wird diese Methode ebenfalls neu definieren, was zu Kompilierungsfehlern oder ungelösten externen Fehlern führen kann.
Eine andere Möglichkeit besteht darin, die globalen Neu- und Löschoperatoren zu überschreiben. Dies ist eine viel sauberere Lösung, aber es schlägt fehl, wenn Sie eine Bibliothek von Drittanbietern haben, die eine neue in die Bibliothek stellt, aber das Löschen in der Kopfzeile (oder umgekehrt).
Wie wird die Quelle des Anrufs ermittelt? Wenn new, delete, ... mit # define's abgefangen werden, werden oft die Präprozessorsymbole __FILE__
und __LINE__
verwendet, um die Quelle des Lecks zu erhalten. Wenn Sie in Ihrem Code jedoch "generische" Funktionen wie z. CreateString (), dann werden die meisten Lecks in diesen generischen Funktionen gemeldet, was Ihnen nicht wirklich hilft.
Alternativ können Sie den Aufrufstapel zur Laufzeit abrufen. Es kann recht einfach mit der Windows StackWalk-Funktion durchgeführt werden, aber meiner Erfahrung nach ist das sehr sehr langsam. Eine viel schnellere Alternative besteht darin, den Basiszeiger direkt zu holen und sich auf die Stack-Frame-Pointer zu verlassen (Sie müssen mit / Oy kompilieren, um die Stack-Frame-Pointer zu erhalten). Sie können den Rahmen (Basis) Zeiger wie folgt erhalten: _asm mov DWORD PTR [FramePtr], ebp
. Dann einfach schleifen und in der Schleife den Befehlszeiger von ((ADDR *)FramePtr)[1];
und den nächsten Rahmenzeiger von FramePtr = ((ADDR *)FramePtr)[0];
Wie melden Sie die Lecks genau im Moment? In meinem Fall möchte ich, dass die Lecks am Ende der Anwendung gemeldet werden. Um dies jedoch zu ermöglichen, benötigen Sie am Ende Ihrer Anwendung einen Mechanismus zur Meldung von Lecks. Dies bedeutet, dass Sie, wenn Sie Ihre Lecks selbst melden möchten, darauf angewiesen sind, dass globale Variablen am Ende Ihrer Anwendung zerstört werden (und die Lecks in diesem Destruktor der globalen Variablen melden). Bei serverartigen Anwendungen sind Sie wahrscheinlich eher daran interessiert, die Speicherbelegung zwischen zwei Zeitpunkten zu unterscheiden.
Und jetzt die verschiedenen Lecksysteme:
C RunTime: Meldet Lecks am Ende, hat aber keine anständige Möglichkeit, Anruflisten zu melden. Die Methode zum Abfangen von Aufrufen auf new, delete, ... kann Probleme bei Kombinationen mit Bibliotheken von Drittanbietern (wie Qt, Boost, ...) verursachen.
Externe Microsoft-Dienstprogramme (wie GFlags, UMDH ,, ...): Sie scheinen nur Unterschiede zwischen zwei Zeitpunkten zu protokollieren. Der Aufruf-Stack scheint jedoch viel besser zu sein, obwohl das GFlags-Dienstprogramm Flags im Betriebssystem festlegen kann, die eine ernsthafte Verlangsamung Ihrer Anwendung verursachen können.
Sichtlecksuchgerät. Scheint, alle Lecks richtig zu finden, aber in meinem Fall funktioniert es nicht, da ich eine 3rd-Party-DLL habe, die einfach den Prozess bei seinem DllUnload abbricht (scheint ein Windows 7-spezifisches Problem zu sein).
Mein persönlicher Favorit (und die Leute werden mir nicht zustimmen, da bin ich mir sicher) ist es, einen eigenen Speichermanager zu schreiben. Das Abfangen kann leicht mit den globalen Operatoren "new" und "delete" erfolgen (mit den oben genannten möglichen Problemen), und Sie können den Aufruf-Stack wie oben beschrieben erhalten. Diese Alternative beruht auch darauf, einen Code zu haben, der im allerletzten Moment in Ihrer Anwendung ausgeführt wird.
Bei der Auswahl einer Alternative fand ich folgende Aspekte sehr wichtig für meine Situation:
Hoffe, das hilft.
Dies ist die Ausgabe von Visual Studio eigenen Debug CRT, nicht die Ausgabe von Visual Leak Detector. Stellen Sie zunächst sicher, dass Sie die aktuelle Version unter Codeplex verwenden und dass Sie vld.h in Ihrem Projekt enthalten haben. Sie erhalten eine viel informativere Ausgabe.
Sie sollten Valgrind verwenden, es ist sehr mächtig und erklärt genau, wo die Lecks in Ihrem Programm sind. Ihr Programm muss möglicherweise mit gcc kompiliert werden, obwohl ...
Rational Purify ist als kostenpflichtiges Plugin für VC ++ erhältlich und ist sehr gut Leck (und andere Probleme) Detektor. Ich habe es oft unter Solaris verwendet, und es war sehr einfach zu verwenden und zu löschen. Ich habe auch von anderen Leuten gute Dinge über die Version für die Verwendung mit Visual Studio gehört, aber das habe ich noch nie probiert.
FWIW, ich vermute, dass Purify die Inspiration für Valgrind war, was bereits erwähnt wurde.Wenn die Zuordnungsnummern (die in den gewellten Klammern) immer gleich sind, Das könnte helfen . Im Grunde wurde beschrieben, wie VC ++ einen Haltepunkt generieren kann, wenn die Zuweisung mit der angegebenen Nummer versucht wird.
Tags und Links memory-leaks c++ visual-c++ visual-leak-detector