Frage

Das ist etwas hypothetisch und stark vereinfacht, aber ...

Gehen Sie von einem Programm aus, das von Dritten geschriebene Funktionen aufruft.Es kann davon ausgegangen werden, dass diese Parteien nicht feindselig sind, aber nicht als „kompetent“.Jede Funktion akzeptiert einige Argumente, hat Nebenwirkungen und gibt einen Wert zurück.Sie haben keinen Status, solange sie nicht ausgeführt werden.

Das Ziel besteht darin, sicherzustellen, dass sie keine Speicherlecks verursachen können, indem alle Mallocs (und dergleichen) protokolliert und dann nach Beendigung der Funktion alles freigegeben wird.

Ist das möglich?Ist das praktisch?

p.s.Für mich ist es wichtig, sicherzustellen, dass keine Zuweisungen bestehen bleiben. Daher sind Möglichkeiten, Speicherlecks zu entfernen, ohne dies zu tun, für mich nicht sinnvoll.

War es hilfreich?

Lösung

Sie geben weder das Betriebssystem noch die Umgebung an, diese Antwort setzt Linux, glibc und C voraus.

Sie können __malloc_hook, __free_hook und __realloc_hook so einstellen, dass sie auf Funktionen verweisen, die jeweils von malloc(), realloc() und free() aufgerufen werden.Es gibt eine __malloc_hook-Manpage, die die Prototypen zeigt.Sie können in diesen Hooks Spurzuweisungen hinzufügen und dann zurückkehren, damit glibc die Speicherzuweisung/-freigabe übernimmt.

Es hört sich so an, als ob Sie alle Live-Zuweisungen freigeben möchten, wenn die Drittanbieterfunktion zurückkehrt.Es gibt Möglichkeiten, gcc mithilfe von -finstrument-functions automatisch Aufrufe an jedem Funktionseingang und -ausgang einfügen zu lassen, aber ich denke, das wäre für das, was Sie versuchen, unelegant.Können Sie mit Ihrem eigenen Code eine Funktion in Ihrer Speicherverfolgungsbibliothek aufrufen, nachdem Sie eine dieser Funktionen von Drittanbietern aufgerufen haben?Anschließend können Sie prüfen, ob es Zuweisungen gibt, die die Drittanbieterfunktion nicht bereits freigegeben hat.

Andere Tipps

Zunächst müssen Sie die Einstiegspunkte bereitstellen malloc() Und free() und Freunde.Da dieser Code bereits kompiliert ist (oder?), können Sie sich nicht darauf verlassen #define umleiten.

Anschließend können Sie diese auf die offensichtliche Weise implementieren und protokollieren, dass sie von einem bestimmten Modul stammen, indem Sie diese Routinen mit diesen Modulen verknüpfen.

Der schnellste Weg beinhaltet überhaupt keine Protokollierung. Wenn die von ihnen verwendete Speichermenge begrenzt ist, warum nicht den gesamten „Heap“, den sie jemals benötigen, vorab zuweisen und daraus einen Allokator schreiben?Wenn es fertig ist, geben Sie den gesamten „Heap“ frei und fertig!Sie könnten diese Idee auf mehrere Heaps erweitern, wenn sie komplexer ist.

Wenn Sie wirklich „protokollieren“ müssen und keinen eigenen Allokator erstellen müssen, finden Sie hier einige Ideen.Erstens: Verwenden Sie eine Hash-Tabelle mit Zeigern und interner Verkettung.Eine andere Möglichkeit wäre, vor jedem Block zusätzlichen Platz zuzuweisen und dort Ihre eigene Struktur einzufügen, die beispielsweise einen Index in Ihrer „Protokolltabelle“ enthält, und dann eine freie Liste von Protokolltabelleneinträgen zu führen (als Stapel, sodass Sie eine freie Liste erhalten). oder einen freien zurückzusetzen ist O(1)).Dies benötigt mehr Speicher, sollte aber schnell sein.

Ist es praktisch?Ich denke, das ist der Fall, solange die Geschwindigkeitseinbuße akzeptabel ist.

Sie können die Funktionen von Drittanbietern in einem separaten Prozess ausführen und den Prozess schließen, wenn Sie mit der Verwendung der Bibliothek fertig sind.

Eine bessere Lösung als der Versuch, Mallocs zu protokollieren, könnte darin bestehen, die Funktionen beim Aufruf in eine Sandbox zu setzen – ihnen Zugriff auf ein festes Speichersegment zu gewähren und dieses Segment dann freizugeben, wenn die Ausführung der Funktion abgeschlossen ist.

Eine unbeschränkte, inkompetente Speichernutzung kann genauso schädlich sein wie bösartiger Code.

Können Sie sie nicht einfach zwingen, ihren gesamten Speicher auf dem Stapel zuzuweisen?Auf diese Weise wäre garantiert, dass es nach Beendigung der Funktion freigegeben wird.

In der Vergangenheit habe ich eine Softwarebibliothek in C geschrieben, die über ein Speicherverwaltungssubsystem verfügte, das die Möglichkeit enthielt, Zuweisungen und Freigaben zu protokollieren und jede Zuweisung und Freigabe manuell abzugleichen.Dies war bei der Suche nach Speicherlecks von Nutzen, die Anwendung war jedoch schwierig und zeitaufwändig.Die Anzahl der Protokolle war überwältigend und es dauerte sehr lange, die Protokolle zu verstehen.

Wenn Ihre Drittanbieter-Bibliothek jedoch über umfangreiche Zuweisungen verfügt, ist es höchstwahrscheinlich unpraktisch, dies über die Protokollierung zu verfolgen.Wenn Sie in einer Windows-Umgebung arbeiten, würde ich die Verwendung eines Tools wie Purify[1] oder BoundsChecker[2] empfehlen, das in der Lage sein sollte, Lecks in Ihren Drittanbieter-Bibliotheken zu erkennen.Die Investition in das Werkzeug dürfte sich durch die Zeitersparnis amortisieren.

[1]: http://www-01.ibm.com/software/awdtools/purify/ Reinigen

[2]: http://www.compuware.com/products/devpartner/visualc.htm GrenzenChecker

Da Sie sich Sorgen über Speicherlecks machen und über malloc/free sprechen, gehe ich davon aus, dass Sie sich in C befinden.Aufgrund Ihrer Frage gehe ich auch davon aus, dass Sie keinen Zugriff auf den Quellcode der Drittanbieterbibliothek haben.

Das Einzige, was mir einfällt, ist, den Speicherverbrauch Ihrer App vor und nach dem Anruf zu untersuchen, Fehlermeldungen zu protokollieren, wenn sie unterschiedlich sind, und den Drittanbieter davon zu überzeugen, alle gefundenen Lecks zu beheben.

Wenn Sie Geld übrig haben, sollten Sie Purify zur Nachverfolgung von Problemen in Betracht ziehen.Es wirkt Wunder und erfordert keinen Quellcode oder eine Neukompilierung.Es gibt auch andere Debugging-Malloc-Bibliotheken, die günstiger sind.Elektrozaun ist ein Name, an den ich mich erinnere.Allerdings scheinen auch die von Denton Gentry erwähnten Debugging-Hooks interessant zu sein.

Wenn Sie zu arm für Purify sind, versuchen Sie es mit Valgrind.Es ist viel besser als vor 6 Jahren und viel einfacher einzutauchen als Purify.

Microsoft Windows bietet (verwenden Sie SUA, wenn Sie POSIX benötigen) möglicherweise die fortschrittlichste Heap-Infrastruktur (andere APIs, von denen bekannt ist, dass sie den Heap verwenden) aller heute verfügbaren Betriebssysteme.

Die __malloc()-Debug-Hooks und die zugehörigen CRT-Debug-Schnittstellen eignen sich gut für Fälle, in denen Sie über den Quellcode für die Tests verfügen. Sie können jedoch häufig Zuweisungen durch Standardbibliotheken oder anderen verlinkten Code übersehen.Dies wird erwartet, da es sich um die Heap-Debugging-Infrastruktur von Visual Studio handelt.

gflags ist ein sehr umfassender und detaillierter Satz von Debugfunktionen, der seit vielen Jahren in Windows enthalten ist.Erweiterte Funktionalität für reine Quell- und Binäranwendungsfälle (da es sich um die Betriebssystem-Heap-Debugging-Infrastruktur handelt).

Es kann Full-Stack-Traces (Neugliederung symbolischer Informationen in einem Nachbearbeitungsvorgang) aller Heap-Benutzer und aller Heap-modifizierenden Einstiegspunkte bei Bedarf seriell protokollieren.Außerdem kann es den Heap bei pathalogischen Fällen modifizieren, was die Zuweisung von Daten so ausrichten kann, dass der vom VM-System angebotene Seitenschutz optimal zugewiesen wird (d. h.Ordnen Sie Ihren angeforderten Heap-Block am Ende einer Seite zu, sodass zum Zeitpunkt des Überlaufs sogar ein einzelner Byte-Überlauf erkannt wird.

umdh ist ein Tool, das dabei helfen kann, den Status an verschiedenen Prüfpunkten zu bewerten. Die Daten werden jedoch während der Ausführung des Ziels kontinuierlich gesammelt, sodass es sich im herkömmlichen Kontext nicht um einen einfachen Prüfpunkt-Debug-Stopp handelt.Auch, WARNUNG, Zuletzt habe ich zumindest überprüft, dass die Gesamtgröße des Ringpuffers, in dem die Stapelinformationen für jede Anforderung gespeichert sind, etwas klein ist (64.000 Einträge (Einträge + Stapel)), sodass Sie für Benutzer mit hohem Heap-Speicher möglicherweise einen schnellen Speicherauszug benötigen.Es gibt andere Möglichkeiten, auf diese Daten zuzugreifen, aber umdh ist ziemlich einfach.

NOTIZ es gibt 2 Modi;

  1. MODUS 1, umdh {-p:Prozess-ID|-pn:Prozessname} [-f:Dateiname] [-g]
  2. MODUS 2, umdh [-d] {Datei1} [Datei2] [-f:Dateiname]

    Ich weiß nicht, welcher Wahnsinn den Entwickler erfasst hat, der sich dafür entschieden hat, zwischen -p:foo-Argumentspezifizierern und der nackten Reihenfolge der Argumente zu wechseln, aber es kann ein wenig verwirrend werden.

Das Debugging-SDK funktioniert mit einer Reihe anderer Tools, memsnap ist ein Tool, das sich offenbar auf Speicherverluste und dergleichen konzentriert, aber ich habe es nicht verwendet, Ihr Kilometerstand kann variieren.

Führt gflags ohne Argumente für den UI-Modus aus, +args und /args schon anders "Nutzungsarten" auch.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top