Alle in diesem Block erwähnten Funktionen sind Bibliotheksfunktionen. Wie kann ich dieses Speicherleck beheben?
Es ist unter „Immer noch erreichbar” Kategorie. (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)
Fang: Nachdem ich mein Programm ausgeführt hatte, gab es keine Speicherlecks, aber es hatte 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 dazu 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);
}
Es gibt mehr als eine Möglichkeit, “Speicherleck” zu definieren. Insbesondere gibt es zwei primäre Definitionen von “Speicherlecks”, die unter Programmierern allgemein verwendet werden.
Die erste häufig verwendete Definition von “Speicherleck” lautet: “Speicher wurde zugewiesen und anschließend nicht freigegeben, bevor das Programm beendet wurde.” Viele Programmierer argumentieren jedoch (zu Recht), dass bestimmte Arten von Speicherlecks, die dieser Definition entsprechen, eigentlich kein Problem darstellen und daher nicht berücksichtigt werden sollten Stimmt „Erinnerungsverluste“.
Eine wohl strengere (und nützlichere) Definition von „Speicherleck“ lautet: „Speicher wurde zugewiesen und kann nicht nachträglich freigegeben werden, weil 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. Solcher Speicher ist daher ein „Speicherleck“. Valgrind verwendet diese strengere Definition des Begriffs “Speicherleck”. Dies ist die Art von Leck, die möglicherweise eine erhebliche Heap-Erschöpfung verursachen kann, insbesondere bei langlebigen Prozessen.
Die Kategorie „immer noch erreichbar“ in Valgrinds Leckbericht bezieht sich auf Zuordnungen, die nur der ersten Definition von „Speicherleck“ entsprechen. Diese Blöcke wurden nicht freigegeben, aber sie hätten freigegeben werden können (wenn der Programmierer gewollt hätte), weil das Programm immer noch Zeiger auf diese Speicherblöcke verfolgte.
Generell muss man sich um „noch erreichbare“ Blöcke keine Gedanken machen. Sie stellen nicht die Art von Problem dar Stimmt Speicherlecks können dazu führen. Zum Beispiel gibt es normalerweise kein Potenzial für Heap-Erschöpfung von “noch erreichbaren” Blöcken. Dies liegt daran, dass es sich bei diesen Blöcken normalerweise um einmalige Zuweisungen handelt, auf die während der gesamten Lebensdauer des Prozesses verwiesen wird. Sie könnten zwar durchgehen und sicherstellen, dass Ihr Programm frei wird alle zugewiesenen Speicher, hat dies normalerweise keinen praktischen Nutzen, da das Betriebssystem ohnehin den gesamten Speicher des Prozesses zurückfordert, nachdem der Prozess beendet wurde. Vergleichen Sie dies mit Stimmt Speicherlecks, die, wenn sie nicht behoben werden, dazu führen können, dass einem Prozess nicht mehr genügend Speicher zur Verfügung steht, wenn er lange genug läuft, oder einfach dazu führen, dass ein Prozess weit mehr Speicher als nötig verbraucht.
Wahrscheinlich ist es nur dann sinnvoll, sicherzustellen, dass alle Zuweisungen übereinstimmende “Freigaben” haben, wenn Ihre Lecksuchwerkzeuge nicht erkennen können, welche Blöcke “noch erreichbar” sind (aber Valgrind kann dies tun) oder wenn Ihr Betriebssystem nicht alle zurückfordert Speicher eines beendenden Prozesses (alle Plattformen, für die Valgrind portiert wurde, um dies zu tun).
Können Sie vermuten, was munmap() tut, das die “noch erreichbaren” Blöcke verschwinden lässt?
– Benutzer191776
4. Oktober 2010 um 18:38 Uhr
@crypto: Das könnte sein munmap wird als Ergebnis des Entladens eines gemeinsam genutzten Objekts aufgerufen. Und alle vom gemeinsam genutzten Objekt verwendeten Ressourcen werden möglicherweise freigegeben, bevor es entladen wird. Dies könnte erklären, warum die „noch erreichbaren“ in der befreit werden munmap Fall. Ich spekuliere hier aber nur. Es gibt hier nicht genug Informationen, um es mit Sicherheit zu sagen.
– Dan Formen
4. Oktober 2010 um 19:11 Uhr
Ein Fall, in dem “noch erreichbarer” Speicher als Speicherleck angesehen werden kann: Nehmen Sie an, Sie haben eine Hash-Tabelle, in der Sie Zeiger auf Heap-zugewiesenen Speicher als Wert hinzufügen. Wenn Sie ständig neue Einträge in die Tabelle einfügen, aber die nicht mehr benötigten nicht entfernen und freigeben, kann sie auf unbestimmte Zeit wachsen und Heap-Speicherereignisse verlieren, wenn dieser Speicher thenisch “noch erreichbar” ist. Dies ist der Fall eines Speicherlecks, das Sie in Java oder anderen Garbage Collection-Sprachen haben können.
“Das argumentieren viele Programmierer (zu Recht). [leaked memory] nicht wirklich posieren [a] Problem und sollten daher nicht als echte Speicherlecks betrachtet werden” – Lol … Erstellen Sie eine native DLL mit dieser Art von Speicherleck und lassen Sie sie dann von Java oder .Net verbrauchen. Java und .Net laden und entladen DLLs tausende Male während der Lebensdauer eines Programms. Jedes Mal, wenn die DLL neu geladen wird, verliert sie etwas mehr Speicher. Langlaufenden Programmen wird schließlich der Arbeitsspeicher ausgehen. Es treibt Debians OpenJDK-Betreuer in den Wahnsinn. Er sagte dasselbe auf der OpenSSL-Mailingliste, während wir über die „gutartigen“ Speicherlecks von OpenSSL diskutierten.
– jww
23. August 2018 um 16:20 Uhr
Jens Gustedt
Da sich unten eine Routine aus der pthread-Familie befindet (aber ich kenne diese nicht), würde ich vermuten, dass Sie einen Thread als verknüpfbar gestartet haben, der die Ausführung beendet hat.
Die Exit-Statusinformationen dieses Threads werden bis zu Ihrem Aufruf verfügbar gehalten pthread_join. Somit wird der Speicher bei Programmende in einem Verlustprotokoll gehalten, ist aber immer noch erreichbar, da Sie ihn verwenden könnten pthread_join um darauf zuzugreifen.
Wenn diese Analyse richtig ist, starten Sie diese Threads entweder losgelöst oder treten Sie ihnen bei, bevor Sie Ihr Programm beenden.
Bearbeiten: Ich habe Ihr Beispielprogramm ausgeführt (nach einigen offensichtlichen Korrekturen) und ich habe keine Fehler, aber die folgenden
Seit der dl- Die Sache ähnelt weitgehend dem, was Sie sehen. Ich schätze, Sie sehen ein bekanntes Problem, für das es eine Lösung in Form einer Unterdrückungsdatei gibt valgrind. Vielleicht ist Ihr System nicht auf dem neuesten Stand oder Ihre Distribution unterstützt diese Dinge nicht. (Meins ist Ubuntu 10.4, 64bit)
Ich erhalte 0 Fehler, genau wie Sie. Bitte überprüfen Sie die Leak-Zusammenfassung auf Informationen zu den “Leaks”.
– Benutzer191776
5. Oktober 2010 um 6:16 Uhr
@Krypto: Ich verstehe nicht. Sie meinen, Sie haben die gleichen Verdrängungen wie ich?
– Jens Gustedt
5. Oktober 2010 um 7:11 Uhr
used_suppression: 14 dl-hack3-cond-1 <- das bekomme ich
– Benutzer191776
5. Oktober 2010 um 8:14 Uhr
Hier ist eine angemessene Erklärung für “noch erreichbar”:
„Noch erreichbar“ sind Lecks, die globalen und statisch-lokalen Variablen zugeordnet sind. Da valgrind globale und statische Variablen verfolgt, kann es Speicherzuweisungen ausschließen, die “einmal und vergessen” zugewiesen werden. Eine globale Variable, der einmal eine Zuweisung zugewiesen und diese Zuweisung nie neu zugewiesen wurde, ist typischerweise kein “Leck” in dem Sinne, dass sie nicht unbegrenzt wächst. Es ist immer noch ein Leak im engeren Sinne, kann aber normalerweise ignoriert werden, es sei denn, Sie sind pedantisch.
Lokale Variablen, denen Zuweisungen zugewiesen und nicht freigegeben werden, sind fast immer Lecks.
Valgrind wird working_buf als „noch erreichbar – 16k“ und temp_buf als „definitiv verloren – 5k“ melden.
Du scheinst nicht zu verstehen was still reachable meint.
Irgendetwas still reachable ist nicht ein Leck. Sie müssen nichts dagegen tun.
Für zukünftige Leser könnte “Noch erreichbar” bedeuten, dass Sie vergessen haben, so etwas wie eine Datei zu schließen. Obwohl es in der ursprünglichen Frage nicht so aussieht, sollten Sie immer sicherstellen, dass Sie dies getan haben.
Valgrind meldet nur durchgesickerte Dateideskriptoren mit --track-fds=yes. Sie werden nicht als „noch erreichbar“ gemeldet.
– ZachB
15. Dezember 2020 um 0:30 Uhr
Nun, wenn es mit geöffnet wurde fopendann wird das Leck für die sein FILE Struktur.
– Syockit
5. Januar 2021 um 2:28 Uhr
Valgrind meldet nur durchgesickerte Dateideskriptoren mit --track-fds=yes. Sie werden nicht als „noch erreichbar“ gemeldet.
– ZachB
15. Dezember 2020 um 0:30 Uhr
Nun, wenn es mit geöffnet wurde fopendann wird das Leck für die sein FILE Struktur.
– Syockit
5. Januar 2021 um 2:28 Uhr
14251900cookie-checkNoch erreichbares Leck von Valgrind entdecktyes
Valgrind-FAQ.
– jww
23. August 2018 um 17:40 Uhr