Alle in diesem Block genannten Funktionen sind Bibliotheksfunktionen. Wie kann ich diesen Speicherverlust beheben?
Es ist in der Kategorie " Noch erreichbar " aufgeführt. (Es gibt 4 weitere, die sehr ähnlich sind, aber unterschiedliche Größen haben)
630 bytes in 1 blocks are still reachable in loss record 5 of 5
at 0x4004F1B: calloc (vg_replace_malloc.c:418)
by 0x931CD2: _dl_new_object (dl-object.c:52)
by 0x92DD36: _dl_map_object_from_fd (dl-load.c:972)
by 0x92EFB6: _dl_map_object (dl-load.c:2251)
by 0x939F1B: dl_open_worker (dl-open.c:255)
by 0x935965: _dl_catch_error (dl-error.c:178)
by 0x9399C5: _dl_open (dl-open.c:584)
by 0xA64E31: do_dlopen (dl-libc.c:86)
by 0x935965: _dl_catch_error (dl-error.c:178)
by 0xA64FF4: __libc_dlopen_mode (dl-libc.c:47)
by 0xAE6086: pthread_cancel_init (unwind-forcedunwind.c:53)
by 0xAE61FC: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126)
Catch: Nachdem ich mein Programm ausgeführt hatte, gab es keine Speicherlecks, aber es gab eine zusätzliche Zeile in der Valgrind-Ausgabe, die vorher nicht vorhanden war:
Verwerfen von Syms bei 0x5296fa0-0x52af438 in /lib/libgcc_s-4.4.4-20100630.so.1 aufgrund von munmap ()
Wenn das Leck nicht behoben werden kann, kann jemand zumindest erklären, warum die Zeile munmap () Valgrind veranlasst, 0 "noch erreichbare" Lecks zu melden?
Bearbeiten:
Hier ist ein minimales Testbeispiel:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *runner(void *param) {
/* some operations ... */
pthread_exit(NULL);
}
int n;
int main(void) {
int i;
pthread_t *threadIdArray;
n=10; /* for example */
threadIdArray = malloc((n+n-1)*sizeof(pthread_t));
for(i=0;i<(n+n-1);i++) {
if( pthread_create(&threadIdArray[i],NULL,runner,NULL) != 0 ) {
printf("Couldn't create thread %d\n",i);
exit(1);
}
}
for(i=0;i<(n+n-1);i++) {
pthread_join(threadIdArray[i],NULL);
}
free(threadIdArray);
return(0);
}
Laufen Sie mit:
valgrind -v --leak-check=full --show-reachable=yes ./a.out
Antworten:
Es gibt mehr als eine Möglichkeit, "Speicherverlust" zu definieren. Insbesondere gibt es zwei primäre Definitionen von "Speicherverlust", die unter Programmierern gebräuchlich sind.
Die erste häufig verwendete Definition von "Speicherverlust" lautet: "Speicher wurde zugewiesen und wurde anschließend nicht freigegeben, bevor das Programm beendet wurde." Viele Programmierer argumentieren jedoch (zu Recht), dass bestimmte Arten von Speicherlecks, die dieser Definition entsprechen, tatsächlich kein Problem darstellen und daher nicht als echte "Speicherlecks" betrachtet werden sollten.
Eine wohl strengere (und nützlichere) Definition von "Speicherverlust" lautet: "Speicher wurde zugewiesen und kann anschließend nicht freigegeben werden, da das Programm keine Zeiger mehr auf den zugewiesenen Speicherblock hat." Mit anderen Worten, Sie können keinen Speicher freigeben, auf den Sie keine Zeiger mehr haben. Ein solcher Speicher ist daher ein "Speicherverlust". Valgrind verwendet diese strengere Definition des Begriffs "Speicherverlust". Dies ist die Art von Leck, die möglicherweise zu einer erheblichen Erschöpfung des Heapspeichers führen kann, insbesondere bei langlebigen Prozessen.
Die Kategorie "noch erreichbar" im Leckbericht von Valgrind bezieht sich auf Zuordnungen, die nur der ersten Definition von "Speicherverlust" entsprechen. Diese Blöcke wurden nicht freigegeben, aber sie hätten freigegeben werden können (wenn der Programmierer dies gewollt hätte), da das Programm immer noch Zeiger auf diese Speicherblöcke verfolgte.
Im Allgemeinen müssen Sie sich keine Gedanken über "noch erreichbare" Blöcke machen. Sie stellen nicht das Problem dar, das echte Speicherlecks verursachen können. Beispielsweise besteht normalerweise kein Potenzial für eine Erschöpfung des Haufens durch "noch erreichbare" Blöcke. Dies liegt daran, dass es sich bei diesen Blöcken normalerweise um einmalige Zuordnungen handelt, auf die während der gesamten Lebensdauer des Prozesses verwiesen wird. Sie können zwar sicherstellen, dass Ihr Programm den gesamten zugewiesenen Speicher freigibt, dies hat jedoch normalerweise keinen praktischen Vorteil, da das Betriebssystem ohnehin den gesamten Speicher des Prozesses nach Beendigung des Prozesses zurückfordert. Vergleichen Sie dies mit wahr Speicherlecks, die, wenn sie nicht behoben werden, dazu führen können, dass einem Prozess der Speicher ausgeht, wenn sie lange genug ausgeführt werden, oder einfach dazu führen, dass ein Prozess viel mehr Speicher verbraucht als erforderlich.
Wahrscheinlich ist es nur dann sinnvoll sicherzustellen, dass alle Zuordnungen übereinstimmende "Freigaben" haben, wenn Ihre Leckerkennungstools nicht erkennen können, welche Blöcke "noch erreichbar" sind (Valgrind kann dies jedoch) oder wenn Ihr Betriebssystem nicht alle zurückfordert Speicher eines abschließenden Prozesses (alle Plattformen, für die Valgrind portiert wurde).
quelle
munmap
wird dies beim Entladen eines gemeinsam genutzten Objekts aufgerufen. Alle vom freigegebenen Objekt verwendeten Ressourcen werden möglicherweise freigegeben, bevor es entladen wird. Dies könnte erklären, warum die "noch erreichbaren" in demmunmap
Fall befreit werden. Ich spekuliere hier nur. Es gibt hier nicht genug Informationen, um sicher zu sein.Da es unten eine Routine aus der pthread-Familie gibt (aber ich kenne diese nicht), würde ich vermuten, dass Sie einen Thread als Joinable gestartet haben, der die Ausführung beendet hat.
Die Informationen zum Exit-Status dieses Threads bleiben verfügbar, bis Sie aufrufen
pthread_join
. Somit wird der Speicher bei Programmbeendigung in einem Verlustprotokoll gespeichert, ist jedoch weiterhin erreichbar, da Siepthread_join
für den Zugriff darauf verwenden können.Wenn diese Analyse korrekt ist, starten Sie diese Threads entweder getrennt oder verbinden Sie sie, bevor Sie Ihr Programm beenden.
Bearbeiten : Ich habe Ihr Beispielprogramm ausgeführt (nach einigen offensichtlichen Korrekturen) und ich habe keine Fehler, aber die folgenden
Da das
dl-
Ding viel von dem ähnelt, was Sie sehen, denke ich, dass Sie ein bekanntes Problem sehen, das eine Lösung in Bezug auf eine Unterdrückungsdatei für hatvalgrind
. Möglicherweise ist Ihr System nicht auf dem neuesten Stand oder Ihre Distribution verwaltet diese Dinge nicht. (Meins ist Ubuntu 10.4, 64bit)quelle
Sie scheinen nicht zu verstehen, was
still reachable
bedeutet.Alles
still reachable
ist kein Leck. Sie müssen nichts dagegen tun.quelle
FILE
Zeiger?Hier ist eine richtige Erklärung für "noch erreichbar":
"Noch erreichbar" sind Lecks, die globalen und statisch-lokalen Variablen zugewiesen sind. Da valgrind globale und statische Variablen verfolgt, kann es Speicherzuordnungen ausschließen, denen "einmalig und vergessen" zugewiesen wurde. Eine globale Variable hat eine Zuordnung einmal zugewiesen und diese Zuweisung nie neu zugewiesen. Dies ist normalerweise kein "Leck" in dem Sinne, dass sie nicht unbegrenzt wächst. Es ist immer noch ein Leck im engeren Sinne, kann aber normalerweise ignoriert werden, es sei denn, Sie sind pedantisch.
Lokale Variablen, denen Zuweisungen zugewiesen und nicht freigegeben wurden, sind fast immer Lecks.
Hier ist ein Beispiel
Valgrind meldet working_buf als "noch erreichbar - 16k" und temp_buf als "definitiv verloren - 5k".
quelle
Für zukünftige Leser bedeutet "Noch erreichbar" möglicherweise, dass Sie vergessen haben, so etwas wie eine Datei zu schließen. Während es in der ursprünglichen Frage nicht so scheint, sollten Sie immer sicherstellen, dass Sie das getan haben.
quelle