malloc-Tool debuggen

Das Debugging von Anwendungen, die den vom Subsystem malloc zugeordneten Speicher nicht verwalten, kann schwierig und mühsam sein. Dies liegt daran, dass es im Allgemeinen keine Synchronizität zwischen dem Einfügen eines Fehlers und der Exposition des resultierenden Symptoms gibt.

Hinzu kommt die inhärente Komplexität der Speicherzuordnung, bei der Tausende von Zuordnungen asynchron und gleichzeitig vorgenommen, rückgängig gemacht und (vielleicht) aufgerufen werden, und zwar in einem Multithread-Kontext, der eine robuste und effiziente Synchronisation erfordert.

Aus diesen Gründen liegt der Fokus unserer Debugging-Tools in erster Linie darauf, die Zeit der Symptomerkennung näher an die Zeit der Fehlereinfügung zu bringen. Dies hilft dem Anwendungsentwickler, genauer zu bestimmen, welcher Codeabschnitt für das Festschreiben des Fehlers verantwortlich ist.

Es wurden viele verschiedene Debugging-Tools für malloc entwickelt. Einige können in Kombination mit anderen Debugging-Tools und mit allen Zuordnungsrichtlinien verwendet werden; andere sind eingeschränkter in ihrer Verwendung. Viele der Debugging-Tools verbrauchen zusätzlich zu den für den Prozess erforderlichen Ressourcen. Es ist Aufgabe des Anwendungsentwicklers, bei Bedarf ausreichende Ressourcen bereitzustellen.

Leistungsaspekte

Die Debug-malloc-Tools sind für die Verwendung in Vollzeit, konstant oder systemweit nicht geeignet. Obwohl sie für einen minimalen Leistungseinfluss auf die Anwendung, für die das Debugging ausgeführt wird, konzipiert sind, können erhebliche negative Auswirkungen auf den Gesamtsystemdurchsatz auftreten, wenn sie weit verbreitet in einem System eingesetzt werden. Insbesondere wird die Einstellung MALLOCDEBUG=catch_overflow in der Datei /etc/environment nicht empfohlen und führt wahrscheinlich zu erheblichen Systemproblemen, wie z. B. einer übermäßigen Belegung des Paging-Bereichs. Die Tools debug malloc sollten nur verwendet werden, um einzelne Anwendungen oder kleine Gruppen von Anwendungen gleichzeitig zu debuggen.

Aufgrund der zusätzlichen Arbeit, die mit der Durchführung verschiedener Laufzeitprüfungen verbunden ist, wird die Leistung des malloc -Subsystems mit aktivierten Debug-malloc-Tools (je nachdem, welches Tool verwendet wird) variabel beeinträchtigt, aber nicht so, dass Anwendungen unbrauchbar werden. Nachdem das Problem behoben wurde, sollten die Debug-malloc-Tools inaktiviert werden, um die malloc -Subsystemleistung wiederherzustellen.

Hinweise zu Platten und Speicher

Wenn die catch_overflow -oder Malloc-Protokolltools aktiviert sind, verbraucht das Subsystem malloc erheblich mehr Speicher.

Für catch_overflowwird jede malloc-Anforderung um das 4096 + 2-fache der Größe von 'unsigned long' erhöht und dann auf das nächste Vielfache des Makros PAGESIZE aufgerundet. catch_overflow kann sich als zu speicherintensiv erweisen, um für sehr große Anwendungen verwendet zu werden, aber für die meisten Anwendungen, die Speicherdebugging benötigen, sollte die zusätzliche Speicherverwendung kein Problem verursachen. Bei großen Anwendungen kann die Verwendung der Optionen debug_range und functionset auf catch_overflow die Speicherbelegung erheblich verringern, sodass das Programm stückweise getestet werden kann.

Für Malloc Log wird ein Zuordnungsdatensatz für jede aktive Zuordnung im Prozess gespeichert. Dieser Speicheraufwand kann minimiert werden, indem eine geringe Anzahl gespeicherter Stackzeiger angegeben wird.

Wenn die Anwendung, für die das Debugging ausgeführt wird, häufig malloc -Subsystemzuordnungsroutinen aufruft, können Probleme mit der Speicherbelegung auftreten, wenn die Debugging-malloc-Tools aktiviert sind, die verhindern könnten, dass die Anwendung in einem einzelnen Segment ordnungsgemäß ausgeführt wird. In diesem Fall kann es hilfreich sein, die Anwendung für den Zugriff auf zusätzlichen Speicher zu aktivieren, indem der Befehl ulimit und die Option -bmaxdata des Befehls ld verwendet werden.

Um mit aktivierten Debug-Malloc-Tools arbeiten zu können, setzen Sie das ulimit für die Variablen data (-d) und stack (-s) wie folgt:
ulimit -d unlimited
ulimit -s unlimited 

Um maximal 8 Segmente für einen 32-Bit-Prozess zu reservieren, muss die Option -bmaxdata als -bmaxdata:0x80000000angegeben werden.

Wenn die Debugging-malloc-Tools inaktiviert sind, können die Standardwerte für ulimit und -bmaxdata wiederhergestellt werden.

Weitere Informationen zum Befehl ulimit und zur Option -bmaxdata finden Sie unter Large Program Support.

Die Debug-malloc-Tools sind für die Verwendung in einigen Debugsituationen nicht geeignet. Da einige der Debug-malloc-Tools den Systemaufwand für eine Seite oder mehr pro Zuordnung erfordern, wird die Speicherbelegung von Programmen, die viele kleine Zuordnungsanforderungen ausgeben, drastisch erhöht. Bei diesen Programmen treten möglicherweise neue Fehler auf, da Speicherzuordnungsanforderungen aufgrund eines Mangels an Speicher oder Paging-Bereich verweigert werden. Diese Fehler sind nicht unbedingt Fehler in dem Programm, für das das Debugging durchgeführt wird, und sie sind keine Fehler im Tool 'debug malloc'.

Ein konkretes Beispiel hierfür ist der X Server, der während seiner Initialisierung und seines Betriebs zahlreiche winzige Zuordnungsanforderungen ausgibt. Jeder Versuch, den X-Server mit den Befehlen X oder xinit mit aktiviertem catch_overflow auszuführen, führt zum Ausfall des X-Servers, da nicht genügend Speicher verfügbar ist. Es ist jedoch möglich, X mit den Optionen debug_range oder functionset stückweise zu debuggen. Bei X-Clients treten im Allgemeinen keine funktionalen Probleme auf, wenn catch_overflow aktiviert ist. Führen Sie die folgenden Schritte aus, um catch_overflow in einem X-Clientprogramm zu verwenden:
  1. Starten Sie den X-Server mit inaktiviertem catch_overflow.
  2. Starten Sie ein Terminalfenster (z. B. dtterm, xterm, aixterm).
  3. Setzen Sie die entsprechenden Umgebungsvariablen in der Terminalfenstersitzung, um catch_overflow zu aktivieren.
  4. Rufen Sie das zu debuggende X Client-Programm innerhalb desselben Fensters auf.

Debug für malloc aktivieren

Debug Malloc ist nicht standardmäßig aktiviert, aber aktiviert und konfiguriert, indem die Umgebungsvariable MALLOCDEBUG auf die entsprechende Option gesetzt wird. Wenn mehrere Optionen erforderlich sind, können diese durch Kommas (,) voneinander getrennt werden. Die im Tandem angeforderten Optionen müssen miteinander kompatibel sein.

Hinweis: Um das Debugging für malloc zu inaktivieren, müssen Sie die Definition der Umgebungsvariablen MALLOCDEBUG mit dem Befehl unset MALLOCDEBUG aufheben.

Malloc-Debugging-Tools

Pufferüberlauferkennung

Speicherverwaltungsfehler werden manchmal dadurch verursacht, dass das Anwendungsprogramm über das Ende eines zugeordneten Puffers hinaus schreibt. Da dies oft keine unmittelbare Konsequenz hat, treten Symptome erst viel später auf, wenn der überschriebene Speicher (der normalerweise zu einer anderen Zuordnung gehört) referenziert wird und die darin ursprünglich gespeicherten Daten nicht mehr enthält.

Mit der Debugoption catch_overflow können Benutzer Speicherüberschreibungen, Überschreibungen, doppelte Freimengen und die Wiederverwendung von freigegebenem Speicher, der von der Subroutine malloc zugeordnet wurde, ermitteln. Speicherprobleme, die vom Tool 'catch_overflow' erkannt werden, führen zu einem Abbruchaufruf oder einer Segmentierungsverletzung (SIGSEGV). Wenn ein Fehler erkannt wird, wird die Anwendung in den meisten Fällen sofort gestoppt und eine Kerndatei erzeugt.

Die Option catch_overflow wirkt sich auf die Zuordnungen der folgenden Zuordnungsrichtlinien und Optionen aus:
  • Standardzuordnungsrichtlinie
  • Watson -Zuordnungsrichtlinie
  • Option Malloc Multiheap
  • Option Malloc Threadcache
  • Option 'malloc Disclaim'

Die Debugoption catch_overflow wird durch Festlegen von MALLOCDEBUG=catch_overflowaktiviert. Dadurch wird die Identifikation von Speicherüberschreibungen und -überschreibungen aktiviert.

ausrichten

Standardmäßig gibt die Subroutine malloc einen Zeiger zurück, der an einer 2-Wort-Grenze ausgerichtet ist. Dies ist notwendig für die Einhaltung von Standards und für Programme, die keine unabgestimmten Speicherzugriffe akzeptieren (z.B. Programme, die DCE-Komponenten verwenden). Aufgrund einer Anfrage in der Implementierung der Option catch_overflow ist es jedoch möglich, dass ein Programm einen Puffer um einen Betrag überschreibt, der kleiner ist als der Ausrichtungswert, ohne von catch_overflowerkannt zu werden. Die Option align kann verwendet werden, um das malloc -Subsystem anzuweisen, diese Standardausrichtung zu ignorieren, um die Anzahl der Bytes zu verringern oder zu eliminieren, durch die ein Puffer ohne Erkennung überschrieben werden kann. Eine benutzerdefinierte Ausrichtung kann für jede Potenz von zwei zwischen 0 und 4096 einschließlich angegeben werden (z. B. 0,1,2,4, ...). Die Werte 0 und 1 werden als identisch behandelt, d. h., es erfolgt keine Speicherausrichtung. Daher führen Speicherzugriffe, die über den zugeordneten Bereich hinausgehen, zu einem SEGFAULT.

Die Option align ist Teil der Option catch_overflow und nur von Bedeutung, wenn catch_overflow aktiviert ist. Um eine vom Standard abweichende Ausrichtung zu aktivieren, legen Sie die Umgebungsvariable MALLOCDEBUG wie folgt fest:
MALLOCDEBUG=catch_overflow,align:n
Dabei ist n die gewünschte Ausrichtung.
Verwenden Sie die folgende Formel, um zu berechnen, wie viele Byte von Overreads oder Überschreibungen die Option catch_overflow für eine bestimmte Zuordnungsanforderung zulässt, wenn n die angeforderte Ausrichtung und Größe die Anzahl der zuzuordnenden Byte ist:
((((size / n) + 1) * n) - size) % n
Das folgende Beispiel veranschaulicht die Auswirkung der Option align auf die Fähigkeit der Anwendung, Überleseoperationen oder Überschreibungen mit aktivierter Option catch_overflow auszuführen. In diesem Beispiel wird die Option align mit dem Wert 2 angegeben:
MALLOCDEBUG=align:2,catch_overflow
Die Option catch_overflow behandelt Overreads und Overwrites wie folgt:
  • Wenn eine gerade Anzahl von Bytes zugeordnet wird, ordnet malloc genau die Anzahl der angeforderten Bytes zu, was 0 Bytes von Overreads oder Overwrites zulässt.
  • Wenn eine ungerade Anzahl von Byte zugeordnet wird, ordnet malloc die Anzahl der angeforderten Byte plus ein zusätzliches Byte zu, um die erforderliche Ausrichtung zu erfüllen. Dies ermöglicht 1 Byte möglicher Überschreibungs-oder Überschreibungen.
override_signal_handling (Signalverarbeitung überschreiben)
Die Option catch_overflow meldet Fehler auf eine der folgenden Arten:
  • Speicherzugriffsfehler (z. B. der Versuch, über das Ende des zugeordneten Speichers hinaus zu lesen oder zu schreiben) führen zu einem Segmentierungsverstoß (SIGSEGV), der zu einem Kernspeicherauszug führt.
  • For other types of errors (such as trying to free space that was already freed), the catch_overflow option will output an error message, then call the abort function , which will send a SIGIOT signal to end the current process.

Wenn das aufrufende Programm die SIGSEGV-und SIGIOT-Signale blockiert oder abfängt, wird verhindert, dass die Option catch_overflow Fehler meldet. Die Option override_signal_handling bietet die Möglichkeit, diese Situation zu umgehen, ohne die Anwendung neu zu codieren und neu zu erstellen.

Wenn die Option override_signal_handling angegeben ist, führt die Option catch_overflow bei jedem Aufruf einer malloc -Subsystemroutine die folgenden Aktionen aus:
  1. Inaktivieren Sie alle vorhandenen Signalhandler, die von der Anwendung für SIGSEGV oder SIGIOT eingerichtet wurden.
  2. Setzen Sie die Aktion für SIGIOT und SIGSEGV auf den Standardwert (SIG_DFL).
  3. Entsperren Sie sowohl SIGIOT als auch SIGSEGV.

Wenn ein Anwendungssignalhandler die Aktion für SIGSEGV zwischen Speicherzuordnungsroutinenaufrufen ändert und dann einen ungültigen Speicherzugriff versucht, kann die Option catch_overflow den Fehler nicht melden (die Anwendung wird nicht beendet und es wird keine Kerndatei erstellt).

Hinweis:
  1. Die Option override_signal_handling kann in einer Threadanwendungsumgebung unwirksam sein, da die Option catch_overflow die Subroutine sigprocmask verwendet und viele Threadprozesse die Subroutine pthread_sigmask verwenden.
  2. Wenn ein Thread die Subroutine sigwait aufruft, ohne SIGSEGV und SIGIOT in die Signalgruppe einzuschließen, und die Option catch_overflow anschließend einen Fehler erkennt, wird der Thread blockiert, da die Option catch_overflow nur SIGSEGV oder SIGIOT generieren kann.
  3. Wenn ein Zeiger auf ungültigen Speicher an eine Kernelroutine übergeben wird, schlägt die Kernelroutine fehl und gibt in der Regel mit der Fehlernummer EFAULT zurück. Wenn die Anwendung die Rückgabe des Systemaufrufs nicht überprüft, wird dieser Fehler möglicherweise nicht erkannt.
Debugbereich

Wenn die Option catch_overflow aktiviert ist, wird die Pufferüberlauferkennung standardmäßig für jede Zuordnung im Programm ausgeführt. Wenn die Option debug_range angegeben wird, werden nur Zuordnungsanforderungen, die zwischen einer benutzerdefinierten minimalen und maximalen Größe liegen, durch die Option catch_overflow Pufferüberläufe erkannt. Andernfalls wird keine Pufferüberlauferkennung ausgeführt. Diese Option ermöglicht es dem Benutzer, die Menge an zusätzlichen Speicherressourcen zu steuern, die von der Option catch_overflow verbraucht werden, indem das Tool in bestimmten Fällen verwendet wird.

Die Option debug_range ist nur im Kontext der Option catch_overflow aussagekräftig. Sie wird wie folgt aktiviert:
MALLOCDEBUG=catch_overflow,debug_range:min:max
Dabei ist min die Untergrenze und max die Obergrenze des Bereichs, in dem die Pufferüberlauferkennung ausgeführt werden soll. Wenn 0 als Mindestwert angegeben wird, wird für alle Elemente, die kleiner als der Maximalwert sind, eine Pufferüberlauferkennung ausgeführt. Wenn 0 als Maximalwert angegeben wird, wird für alle Elemente, die größer als der Mindestwert sind, eine Pufferüberlauferkennung durchgeführt.

Einschränkung:Aufgrund einer internen Implementierungsanforderung muss jede Zuordnung immer noch mindestens eine Seitengröße aufweisen. Daher reduziert die Option debug_range lediglich den Systemaufwand für die Option catch_overflow , anstatt sie zu entfernen.

Wenn die Subroutine realloc mit einer Zuordnungsanforderung aufgerufen wird, die in den benutzerdefinierten Bereich fällt, wird die Pufferüberlauferkennung auch dann ausgeführt, wenn die ursprüngliche Zuordnung nicht innerhalb des angegebenen Bereichs lag. Das Gegenteil ist auch der Fall.

Anmerkung: Wenn die Option override_signal zusammen mit der Option debug_range festgelegt wird, wird das Überschreiben des Signalverhaltens SIGIOT und SIGSEGV für alle Zuordnungen ausgeführt.
Funktionsset

Aufgrund einer internen Implementierungsanforderung muss jede Zuordnung immer noch mindestens eine Seitengröße haben. Daher reduziert die Option functionset lediglich den Systemaufwand für die Option catch_overflow , anstatt sie zu entfernen.

Wenn die Subroutine realloc von einer Funktion aufgerufen wird, die Mitglied der benutzerdefinierten Funktionsliste ist, wird die Pufferüberlauferkennung auch dann ausgeführt, wenn die ursprüngliche Zuordnung nicht von einer angegebenen Funktion vorgenommen wurde. Das Gegenteil ist auch der Fall.

Anmerkung: Wenn die Option override_signal zusammen mit der Option functionset festgelegt wird, wird das Überschreiben des Signalverhaltens SIGIOT und SIGSEGV für alle Zuordnungen ausgeführt.

Die Option functionset überprüft nicht die Gültigkeit der in der Liste angegebenen Funktionen.

'allow_overreading'

Wenn die Debugoption catch_overflow aktiviert ist und das aufrufende Programm versucht, über das Ende des zugeordneten Speichers hinaus zu lesen, tritt standardmäßig eine Segmentierungsverletzung auf und der Prozess erstellt einen Kernspeicherauszug. Der Benutzer ist jedoch möglicherweise nicht daran interessiert, diesen Fehlertyp abzufangen, und hat möglicherweise catch_overflow aktiviert, um gefährlichere Überschreibungen abzufangen. Wenn Sie die Option allow_overreading angeben, ignoriert die Option catch_overflow Überlesevorgänge, sodass andere Fehlertypen, die als schwerwiegender betrachtet werden können, zuerst erkannt werden können.

Die Option allow_overreading ist nur im Kontext der Option catch_overflow aussagekräftig. Sie wird wie folgt aktiviert:
MALLOCDEBUG=catch_overflow,allow_overreading,
'postfree_checking'

Die Option postfree_checking verbraucht eine beträchtliche Menge an zusätzlichem Speicher. Programme mit sehr großem Speicherbedarf können die Option postfree_checking möglicherweise nicht verwenden.

Malloc-Trace

Malloc Trace ist eine Debugoption, die das Tracing aller Aufrufe an die malloc -Subsystem-API über die Systemtracefunktion ermöglicht.

Mallow-Protokoll

Malloc Log ist eine Debugoption, die dem Benutzer eine Laufzeitdatenbank aktiver Zuordnungen im malloc -Subsystem bereitstellt.

Berichtszuordnungen

Die Option report_allocations ist ein Tool zum Erkennen von Speicherlecks in einem Anwendungsprogramm. Die Option report_allocations verwendet die von Malloc Log erstellte Datenbank, um eine Liste der momentan vom Benutzer gehaltenen Zuordnungen zu melden. Jede erfolgreiche Zuordnung wird zum Zeitpunkt der Anforderung durch das Malloc-Protokoll aufgezeichnet. Wenn eine Zuordnung aufgehoben wird, entfernt Malloc Log den zugehörigen Datensatz aus der Datenbank. Beim Prozessexit wird die Liste der noch aktiven Zuordnungen in der Standardfehlerausgabe (stderr) ausgegeben, die eine Liste der Zuordnungen enthält, die nie von ihren aufrufenden Programmen freigegeben wurden.

Für die Option report_allocations ist die Funktionalität von Malloc Log erforderlich. Daher wird das Malloc-Protokoll implizit aktiviert, wenn report_allocations aktiviert ist. Die Option report_allocations ist wie folgt aktiviert:
MALLOCDEBUG=report_allocations
validate_ptrs

Standardmäßig validieren die malloc -Subsystem-APIs ihre Eingabezeiger nicht, um sicherzustellen, dass sie tatsächlich zuvor zugeordneten Speicher referenzieren. Wenn einer dieser Zeiger ungültig ist, kann es zu einer schwerwiegenden Beschädigung des Heapspeichers kommen. Die Angabe der Option validate_ptrs bewirkt, dass die malloc -Subsystem-APIs eine umfassende Validierung ihrer Eingabezeiger durchführen. Wenn ein Zeiger als ungültig erkannt wird (d. h., er verweist nicht auf Speicher, der zuvor durch einen Aufruf der Subsystem-API malloc zugeordnet wurde), wird eine Fehlernachricht ausgegeben, die angibt, warum er ungültig ist, die Abbruchfunktion aufgerufen und eine Kerndatei erstellt. Die Option validate_ptrs ähnelt der Unteroption verbose . Die Option validate_ptrs wird nicht wirksam, wenn die Option postfree_checking aktiviert ist.

Die Option validate_ptrs ist wie folgt aktiviert:
MALLOCDEBUG=validate_ptrs
Malloc-Erkennung

Malloc Detect ist eine Debugoption zum Erkennen und Melden von Beschädigungen der Datenstrukturen des internen malloc -Subsystems bei jedem Aufruf einer malloc -Subsystem-API.

verbose

Unteroption von Malloc Detect

Checkarena

Unteroption von Malloc Detect

output

Standardmäßig senden die malloc-Debugoptionen ihre Ausgabe an stderr. Dies ist möglicherweise nicht für alle Programme erwünscht. Mit der Option output können Sie ein alternatives Ziel für gedruckte Informationen angeben. Die Ausgabe kann entweder an stderr, stdout oder an eine beliebige Datei auf dem System gesendet werden.

Die Option output ist wie folgt aktiviert:
MALLOCDEBUG=output:<filename>
continue

Viele malloc-Debugging-Optionen rufen abort () auf, wenn sie einen Fehler feststellen. Dies ist nicht immer das gewünschte Verhalten für alle Programme. Die Option continue ist vorhanden, um das Subsystem malloc anzuweisen, nach der Erkennung eines synchronen Fehlers fortzufahren, anstatt den Prozess abzubrechen. Fehlernachrichten werden weiterhin in den entsprechenden Kanälen protokolliert.

Die Option continue ist wie folgt aktiviert:
MALLOCDEBUG=continue
Malloc-Debug-Füllung

Malloc debug fill ist eine Debugoption, mit der der Speicher, der über die malloc () -Aufrufe zugeordnet wurde, mit einem benutzerdefinierten Muster für Debugzwecke gefüllt wird.

Das Muster sollte als Zeichenfolge angegeben werden (Beispiel: export MALLOCDEBUG=fill: "abc" legt den über malloc zugeordneten Speicher mit dem Muster "abc" fest). Es sind maximal 128 Zeichen zulässig. Wenn das Muster nicht angegeben wird, wird die Fülloption ignoriert.

Die Option malloc debug fill kann wie folgt aktiviert werden:

MALLOCDEBUG=fill:pattern

Das Muster kann eine Oktal-oder Hexadezimalzahl sein, die in Form einer Zeichenfolge angegeben wird. d. h., das Muster "\101" wird als Oktalschreibweise für Zeichen 'A' und das Muster “\x41”als Hexadezimalschreibweise für Zeichen 'A' behandelt.

Wenn eine ungültige Oktalzahl angegeben wird, z. B. \777, die nicht in 1 Byte enthalten sein kann, wird als \377 der maximale Oktalwert gespeichert, der als 1 Byte gespeichert werden kann.