GCC-Speicherleckerkennung äquivalent zu Microsoft crtdbg.h?

Lesezeit: 6 Minuten

Nach vielen Jahren der Arbeit an einer universellen C++-Bibliothek mit dem Microsoft MSVC-Compiler in Visual Studio portieren wir sie jetzt auf Linux/Mac OS X (bitte für uns). Ich habe mich an den einfachen Speicherleckerkennungsmechanismus in MSVC gewöhnt und ihn sehr gemocht:

#ifdef DEBUG
    #define _CRTDBG_MAP_ALLOC
    #define NEW   new( _NORMAL_BLOCK, __FILE__, __LINE__)
    #include <stdlib.h>
    #include <crtdbg.h>
#else
    #define NEW   new
#endif

Jede Speicherzuweisung erfolgt mit diesem NEUEN Makro. Immer wenn ein Prozess, der unsere Bibliothek verwendet, beendet wird, werden alle Speicherlecks (Blöcke, die nicht freigegeben wurden) auf der Konsole zusammen mit der Datei und Zeilennummer gemeldet, in der der Speicher ursprünglich zugewiesen wurde.

Der Teil, den ich daran mag, ist, dass ich nicht aktiv “mit dem Leistungstool ausführen” oder anderweitig angeben muss, dass ich nach Lecks suche. Leaks werden mir im regulären Verlauf der Entwicklung gemeldet, jedes Mal, wenn ein Prozess beendet wird.

Jetzt, wo wir uns der GCC-Welt zuwenden, stelle ich fest, dass die Tools zur Erkennung von Speicherlecks, von denen viele ziemlich ausgeklügelt sind, erfordern, dass ich ausdrücklich angebe, dass ich mich im Lecksuchmodus befinde. Meine IDE ist Xcode und ich habe mir einige der Zuweisungs-/Leckerkennungstools (wie Instruments und MallocDebug) angeschaut, aber ich gebe zu, dass ich noch nicht die Zeit damit verbracht habe, sie vollständig zu verstehen. Mich irritiert immer wieder, dass ich eigentlich vorher angeben muss, dass ich nach einem Leck suche, anstatt automatisch darauf aufmerksam gemacht zu werden.

Ich verwende Xcode 3.2 und habe gehört, dass es jetzt eine raffinierte Integration mit einem statischen Analysetool gibt, aber auch hier habe ich mich nicht damit befasst. Ich suche nach einer Vorstellung davon, was meine Optionen sind. Gibt es einen vergleichbaren Mechanismus, der in GCC und/oder Xcode integriert ist? Gibt es eine einfache Bibliothek oder ein Tool eines Drittanbieters, das die sehr grundlegenden Funktionen ausführt, die ich kenne und liebe? Oder sollte ich es aufsaugen und die neue Art lernen, Dinge zu tun?

Ihnen stehen eine Reihe von Optionen zur Verfügung.

Erstens, und am beliebtesten, können Sie Ihre Anwendung unter Tools wie ausführen Valgrind. Das sollte Sie auf eine Reihe von Speichermissbrauch hinweisen, wie z. B. NULL-Zeiger-Lese- und Schreibvorgänge und Speicherlecks. Es gibt eine Reihe von Tools in der Valgrind-Suite, also schauen Sie sich diese unbedingt an.

Zweitens können Sie immer eine Bibliothek verwenden, die die verwendet LD_PRELOAD Trick. Grundsätzlich ermöglicht der LD_PRELOAD-Trick die DLL-Injektion, was bedeutet, dass Tools erstellt werden können, mit denen Sie Ihre Speichernutzung in Ihrer Anwendung verfolgen können, ohne etwas zu ändern. Sie finden Tools wie z dmalloc und Verteidigung recht umfangreich in den von ihnen angebotenen Debugging-Möglichkeiten zu sein.

Schließlich enthielten die jüngsten GCC-Versionen ein Tool namens Schmutzfänger. Dies verwendet im Grunde die Funktionsinstrumentierung, um Aufrufe um dieselben Speicherfunktionen wie dmalloc, efence und Valgrind zu wickeln. Das Programm wird merklich langsamer sein und kann zur Laufzeit angepasst werden, obwohl es immer noch so aussieht, als hätte es viel Potenzial.

Ich habe alle drei verwendet und fand Valgrind sehr nützlich. Ich war auch sehr daran interessiert, Mudflap zu verwenden, obwohl ich es noch nicht konnte.

  • +1 für Valgrind. Die Lernkurve ist zunächst etwas steil, aber es ist erstaunlich, nicht neu kompilieren zu müssen.

    – Matthew

    19. November 2009 um 6:58 Uhr

  • Es sieht so aus, als wäre Mudflap im Moment C und “sehr einfaches C++”, was unsere C++-Bibliothek meiner Meinung nach ausschließen würde. Valgrind sieht vielversprechender aus, aber würden Sie Ihre DEBUG-Konfiguration dann immer unter Valgrind ausführen oder würden Sie sie normalerweise nur “hin und wieder” unter Valgrind ausführen, wenn Sie nach Lecks und anderen Speicherfehlern suchen? Mir ist klar, dass Sie beides tun können, aber wie ist Ihr Ansatz?

    – Gene Goykhman

    19. November 2009 um 19:36 Uhr

  • Normalerweise führe ich Valgrind vor Meilensteinen wie Demonstrationen oder Entwicklungskontrollpunkten aus. Ich mache das, weil alle Speicherprobleme, die seit dem letzten Meilenstein aufgetreten sind, immer noch da sind und es gut ist, sauber in jeden Meilenstein zu gehen. Die ständige Ausführung hängt davon ab, worauf Sie sich während der Entwicklung konzentrieren (Leistung im Vergleich zu esoterischen Lecks). Es ist sehr wichtig, dass Sie ein Gefühl für das Tool entwickeln; Es wird Dinge geben, die Sie unterdrücken müssen, und Dinge, die sofort angegangen werden müssen.

    – s1n

    20. November 2009 um 1:57 Uhr

Sie sollten sich “Plattformübergreifender Speicherleckdetektor“, sieht der crtdbg.h-Technik sehr ähnlich.

  • schöne Entdeckung … +1 für die Frage und Antwort.

    – Nikolaus

    23. November 2009 um 11:20 Uhr

Möglicherweise finden Sie auch die Umgebungsvariable MALLOC_CHECK_ nützlich.

Von malloc(3) Manpage:

Neuere Versionen von Linux libc (später als 5.4.23) und glibc (2.x) enthalten eine malloc()-Implementierung, die über Umgebungsvariablen einstellbar ist. Wenn MALLOC_CHECK_ gesetzt ist, wird eine spezielle (weniger effiziente) Implementierung verwendet, die tolerant gegenüber einfachen Fehlern ist, wie z ). Nicht alle derartigen Fehler können jedoch geschützt werden, und Speicherlecks können die Folge sein. Wenn MALLOC_CHECK_ auf 0 gesetzt ist, wird jede erkannte Heap-Beschädigung stillschweigend ignoriert; wenn auf 1 gesetzt, wird eine Diagnosemeldung auf stderr ausgegeben; wenn auf 2 gesetzt, wird abort(3) sofort aufgerufen; wenn auf 3 gesetzt, wird eine Diagnosemeldung auf stderr ausgegeben und das Programm abgebrochen. Die Verwendung eines MALLOC_CHECK_-Werts ungleich Null kann nützlich sein, da es sonst viel später zu einem Absturz kommen kann und die wahre Ursache des Problems dann sehr schwer aufzuspüren ist.

Vielleicht könntest du die gebrauchen Böhm-Müllsammler als Lecksuchgerät:

http://www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html

Von der Website:

#include "leak_detector.h"

main() {
    int *p[10];
    int i;
    /* GC_find_leak = 1; for new collector versions not     */
    /* compiled with -DFIND_LEAK.               */
    for (i = 0; i < 10; ++i) {
    p[i] = malloc(sizeof(int)+i);
    }
    for (i = 1; i < 10; ++i) {
    free(p[i]);
    }
    for (i = 0; i < 9; ++i) {
    p[i] = malloc(sizeof(int)+i);
    }
    CHECK_LEAKS();
}   

(Sie werden über stderr benachrichtigt)

Mir ist nichts “Integriertes” bekannt, das das tut, was Sie beschreiben, aber es scheint nicht sehr schwierig zu sein, Ihre eigene Version davon zu “rollen”. Sie möchten nur, dass Ihr Debugging den Zeiger, die Datei und die Zeile in a neu aufzeichnet map<void*, AllocationInfo> wobei der Schlüssel der zugewiesene Zeiger und der Wert (AllocationInfo) wäre eine Struktur, die den Dateinamen, die Zeilennummer usw. enthält. Sie müssen auch einen benutzerdefinierten Löschoperator definieren, der die Karte auf den zu löschenden Zeiger überprüft. Wenn er gefunden wird, wird dieser Eintrag von der Karte entfernt. Dann geben Sie zum Zeitpunkt des Herunterfahrens des Prozesses den Inhalt der Karte aus.

ich fand eine Seite, auf der jemand sein eigenes selbst entwickeltes System beschreibt, das so funktioniert.

Benutzer-Avatar
Nikolaus

Ich hatte das gleiche Problem, als wir mit der Portierung auf den Mac begannen. “Run with performance tool -> Leaks” war das einzige, was ich gefunden habe und ich bin weniger als begeistert davon … zumindest im Vergleich zu CRTDEBUG. Ich verstehe, dass es einige Optionen gibt (wie von anderen hier beschrieben), aber da wir plattformübergreifend sind, verwenden wir schließlich Windows, um nach den Lecks zu suchen.

Da Sie den statischen Analysator erwähnen. Wir haben einige Zeit damit verbracht, herauszufinden, wie es funktioniert, bis wir herausfanden, dass es nur C, aber nicht C++ unterstützt

Benutzer-Avatar
Dirk Herrmann

Seit einiger Zeit unterstützen sowohl clang als auch gcc einige “Sanitizer”, einschließlich des Leak-Sanitizers. Bei Aktivierung während der Kompilierung wird der Code vom Compiler instrumentiert, um die entsprechenden Prüfungen während der Laufzeit durchzuführen. Auf gcc wird der Leak-Sanitizer mit “-fsanitize=leak” aktiviert. Sehen https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html.

1368960cookie-checkGCC-Speicherleckerkennung äquivalent zu Microsoft crtdbg.h?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy