GLIBC: Debuggen von Speicherlecks: wie die Ausgabe von mtrace zu interpretieren ()
-
03-07-2019 - |
Frage
Ich versuche, ein Speicherleck Problem zu debuggen. Ich verwende mtrace () eine malloc / free / realloc Spur zu bekommen. Ich habe meine prog und haben jetzt eine große Protokolldatei lief. So weit, ist es gut. Aber ich habe Probleme, die Datei zu interpretieren. Betrachten Sie diese Zeilen:
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502570 0x68
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502620 0x30
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1501460 0xa64
Die seltsame daran ist, dass ein Anruf (gleiche Absenderadresse) für 4 Zuweisungen verantwortlich ist.
Noch seltsamer:
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa2c
…
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80
Zwischen diesen beiden Linien der Block 0x2aaab43a1700 freigegeben wird nie zu werden.
Wer weiß, wie dies zu erklären? Wie könnte man in 4 Zuweisungen führen nennen? Und wie malloc könnte eine Adresse zurück, die zuvor bereits zugeteilt wurde?
bearbeiten 2008.09.30: Das Skript des mtrace () -Ausgabe von GLIBC (mtrace.pl) zur Verfügung gestellt zu analysieren ist nicht helfen hier. Es wird nur sagen: Alloc duplizieren 0x2aaab43a1700. Aber wie konnte das passieren?
Lösung
Die Funktion, die den Speicher zuteilt wird mehr als einmal aufgerufen wird. Die Anrufer-Adresse verweist auf den Code, der die Zuweisung getan hat, und diesen Code einfach laufen mehr als einmal wird.
Hier ist ein Beispiel in C:
void *allocate (void)
{
return (malloc(1000));
}
int main()
{
mtrace();
allocate();
allocate();
}
Die Ausgabe von mtrace ist:
Memory not freed: ----------------- Address Size Caller 0x0000000000601460 0x3e8 at 0x4004f6 0x0000000000601850 0x3e8 at 0x4004f6
Beachten Sie, wie die Anrufer-Adresse ist identisch? Aus diesem Grund ist die mtrace Analyse Skript sagt sie identisch sind, weil der gleiche Fehler wird noch einmal gesehen werden, dass in mehreren Speicherverluste zur Folge hat.
Kompilieren mit Debuggt Flags (-g) ist hilfreich, wenn Sie können:
Memory not freed: ----------------- Address Size Caller 0x0000000000601460 0x3e8 at /home/andrjohn/development/playground/test.c:6 0x0000000000601850 0x3e8 at /home/andrjohn/development/playground/test.c:6
Andere Tipps
Sie befinden sich in der direkten Ausgabe von mtrace, die extrem verwirrend und eingängig ist. Glücklicherweise gibt es eine Perl-Skript (genannt mtrace, gefunden in glibc-utils), die sehr leicht die Analyse dieser Ausgabe helfen können.
Stellen Sie sich Ihren Build mit dem Debuggen auf, und führen Sie mtrace wie so:
$ gcc -g -o test test.c
$ MALLOC_TRACE=mtrace.out ./test
$ mtrace test mtrace.out
Memory not freed:
-----------------
Address Size Caller
0x094d9378 0x400 at test.c:6
Die Ausgabe sollte ein Los leichter zu verdauen.
Eine mögliche Erklärung ist, dass die gleiche Funktion verschiedene Puffergrößen ist die Zuteilung? Ein solches Beispiel ist strdup.
Für die zweite Frage ist es möglich, dass die Laufzeit einen „statischen“ scratch Bereich zuzuteilt, die nicht freigegeben werden sollten, bis der Vorgang beendet ist. Und an diesem Punkt, das Betriebssystem ohnehin nach dem Prozess clean-up.
Denken Sie an es auf diese Weise. In Java gibt es keine Destruktoren und keine Garantien, dass die Finalisierung wird jemals für jedes Objekt aufgerufen werden
Versuchen Sie, Ihre App unter valgrind läuft. Es könnte Ihnen eine bessere Sicht über das, was tatsächlich durchgesickert wird.