Ich bin oft auf Speicherlecks gestoßen. Normalerweise, wenn ich so bin, malloc
als gäbe es kein Morgen, oder wenn ich FILE *
wie schmutzige Wäsche baumle. Ich gehe im Allgemeinen davon aus (sprich: hoffe verzweifelt), dass der gesamte Speicher zumindest nach Beendigung des Programms bereinigt wird. Gibt es Situationen, in denen durchgesickerter Speicher nicht erfasst wird, wenn das Programm beendet wird oder abstürzt?
Wenn die Antwort von Sprache zu Sprache sehr unterschiedlich ist, konzentrieren wir uns auf C (++).
Bitte beachten Sie die hyperbolische Verwendung des Ausdrucks "als gäbe es kein Morgen" und "baumeln ... wie schmutzige Wäsche". Unsicheres * malloc
* kann diejenigen verletzen, die Sie lieben. Seien Sie auch bei schmutziger Wäsche vorsichtig.
quelle
calloc
gerne kein Morgen haben. Ausgezeichnet.Antworten:
Betriebssysteme geben alle Ressourcen frei, die von Prozessen beim Beenden gehalten werden.
Dies gilt für alle Ressourcen, die das Betriebssystem verwaltet: Speicher, geöffnete Dateien, Netzwerkverbindungen, Fensterhandles ...
Wenn das Programm jedoch auf einem eingebetteten System ohne Betriebssystem oder mit einem sehr einfachen oder fehlerhaften Betriebssystem ausgeführt wird, kann der Speicher bis zu einem Neustart unbrauchbar werden. Aber wenn Sie in dieser Situation wären, würden Sie diese Frage wahrscheinlich nicht stellen.
Es kann lange dauern, bis das Betriebssystem bestimmte Ressourcen freigibt. Beispielsweise kann es Minuten dauern, bis der TCP-Port, den ein Netzwerkserver zum Akzeptieren von Verbindungen verwendet, frei wird, selbst wenn er vom Programm ordnungsgemäß geschlossen wird. Ein Netzwerkprogramm kann auch entfernte Ressourcen wie Datenbankobjekte enthalten. Das Remote-System sollte diese Ressourcen freigeben, wenn die Netzwerkverbindung unterbrochen wird. Dies kann jedoch noch länger dauern als das lokale Betriebssystem.
quelle
ipcrm
für die manuelle Bereinigung linux.die.net/man/8/ipcrm .Der C-Standard legt nicht fest, dass der von zugewiesene Speicher
malloc
freigegeben wird, wenn das Programm beendet wird. Dies geschieht durch das Betriebssystem und nicht alle Betriebssysteme (normalerweise in der eingebetteten Welt) geben den Speicher frei, wenn das Programm beendet wird.quelle
main
Rückgabe der gesamte von zugewiesene Speichermalloc
freigegeben wird. Beispielsweise heißt es, dass alle geöffneten Dateien vor dem Beenden des Programms geschlossen werden. Für den mir zugewiesenen Speichermalloc
ist er einfach nicht angegeben. Jetzt beschreibt mein Satz über das Betriebssystem natürlich, was normalerweise getan wird, nicht was der Standard vorschreibt, da er nichts dazu spezifiziert.std::atexit
Berücksichtigt auch die Programmbeendigung überstd::exit
, und dann gibt es auchstd::abort
und (C ++ spezifisch)std::terminate
.atexit
wäre , wäre nicht verwendbar. :-)Da alle Antworten die meisten Aspekte Ihrer Frage zu modernen Betriebssystemen abgedeckt haben, gibt es historisch gesehen einen, der erwähnenswert ist, wenn Sie jemals in der DOS-Welt programmiert haben. TSR-Programme ( Terminant and Stay Resident ) geben normalerweise die Kontrolle an das System zurück, befinden sich jedoch im Speicher, der durch einen Software- / Hardware-Interrupt wiederbelebt werden könnte. Es war normal, dass bei der Arbeit mit diesen Betriebssystemen Meldungen wie "Nicht genügend Speicher! Versuchen Sie, einige Ihrer TSRs zu entladen" angezeigt wurden.
Technisch gesehen wird das Programm beendet , aber da es sich immer noch im Speicher befindet, wird kein Speicherverlust ausgelöst, es sei denn, Sie entladen das Programm.
Sie können dies also als einen weiteren Fall betrachten, abgesehen davon, dass Betriebssysteme keinen Speicher zurückfordern, entweder weil es fehlerhaft ist oder weil das eingebettete Betriebssystem dafür ausgelegt ist.
Ich erinnere mich an ein weiteres Beispiel. Das Customer Information Control System (CICS), ein Transaktionsserver, der hauptsächlich auf IBM Mainframes ausgeführt wird, ist pseudokonversativ. Bei der Ausführung werden die vom Benutzer eingegebenen Daten verarbeitet, ein weiterer Datensatz für den Benutzer generiert, an den Benutzerendknoten übertragen und beendet. Beim Aktivieren der Aufmerksamkeitstaste wird sie erneut aktiviert, um einen anderen Datensatz zu verarbeiten. Aufgrund des technischen Verhaltens kann das Betriebssystem keinen Speicher von den abgeschlossenen CICS-Programmen zurückfordern, es sei denn, Sie recyceln den CICS-Transaktionsserver.
quelle
Wie die anderen bereits gesagt haben, werden die meisten Betriebssysteme nach Beendigung des Prozesses den zugewiesenen Speicher zurückfordern (und wahrscheinlich auch andere Ressourcen wie Netzwerksockets, Dateihandles usw.).
Allerdings ist der Speicher möglicherweise nicht das einzige, worüber Sie sich Sorgen machen müssen, wenn Sie mit new / delete (anstelle von raw malloc / free) arbeiten. Der in new zugewiesene Speicher wird möglicherweise zurückgefordert, aber Dinge, die in den Destruktoren der Objekte ausgeführt werden können, werden nicht ausgeführt. Vielleicht schreibt der Destruktor einer Klasse bei Zerstörung einen Sentinel-Wert in eine Datei. Wenn der Prozess gerade beendet wird, wird das Dateihandle möglicherweise geleert und der Speicher zurückgefordert, aber dieser Sentinel-Wert wird nicht geschrieben.
Moral der Geschichte, immer nach sich selbst aufräumen. Lass die Dinge nicht baumeln. Verlassen Sie sich nicht darauf, dass das Betriebssystem nach Ihnen bereinigt wird. Räumen Sie nach sich selbst auf.
quelle
kill -9
Fan zeigt nach oben ...)std::exit
wird dtors anrufen,std::abort
wird nicht, ungefangene Ausnahmen könnten.Dies hängt eher vom Betriebssystem als von der Sprache ab. Letztendlich erhält jedes Programm in einer beliebigen Sprache seinen Speicher vom Betriebssystem.
Ich habe noch nie von einem Betriebssystem gehört, das beim Beenden / Abstürzen eines Programms keinen Speicher recycelt. Wenn Ihr Programm also eine Obergrenze für den Speicher hat, den es zuweisen muss, ist es durchaus sinnvoll, nur zuzuweisen und niemals freizugeben.
quelle
Wenn das Programm jemals in eine dynamische Komponente ("Plugin") umgewandelt wird, die in den Adressraum eines anderen Programms geladen wird, ist dies selbst unter einem Betriebssystem mit ordentlicher Speicherverwaltung problematisch. Wir müssen nicht einmal daran denken, dass der Code auf weniger leistungsfähige Systeme portiert wird.
Auf der anderen Seite, den gesamten Speicher Freigabe kann die Leistung eines Bereinigungsprogramm auswirken.
Bei einem Programm, an dem ich gearbeitet habe, benötigte ein bestimmter Testfall 30 Sekunden oder länger, bis das Programm beendet wurde, da es sich durch das Diagramm des gesamten dynamischen Speichers bewegte und es Stück für Stück freigab.
Eine vernünftige Lösung besteht darin, die Fähigkeit dort zu haben und sie mit Testfällen abzudecken, sie jedoch im Produktionscode auszuschalten, damit die Anwendung schnell beendet wird.
quelle
Alle Betriebssysteme, die den Titel verdienen, bereinigen das Durcheinander, das Ihr Prozess nach der Beendigung verursacht hat. Aber es gibt immer unvorhergesehene Ereignisse. Was ist, wenn der Zugriff irgendwie verweigert wurde und ein armer Programmierer die Möglichkeit nicht vorausgesehen hat und es daher nicht ein bisschen später erneut versucht? Es ist immer sicherer, sich selbst zu bereinigen, wenn Speicherlecks geschäftskritisch sind - ansonsten lohnt sich die Mühe IMO nicht wirklich, wenn diese Mühe kostspielig ist.
Bearbeiten: Sie müssen Speicherlecks beseitigen, wenn sie sich dort befinden, wo sie sich ansammeln, wie in Schleifen. Die Speicherlecks, von denen ich spreche, sind solche, die sich im Laufe des Programms in konstanter Zeit aufbauen. Wenn Sie ein Leck anderer Art haben, wird es höchstwahrscheinlich früher oder später ein ernstes Problem sein.
In technischer Hinsicht sind Ihre Lecks, wenn sie von Speicherkomplexität sind (O), in den meisten Fällen in Ordnung, O (logn) bereits unangenehm (und in einigen Fällen tödlich) und O (N) + unerträglich.
quelle
Der gemeinsam genutzte Speicher auf POSIX-kompatiblen Systemen bleibt bestehen, bis shm_unlink aufgerufen oder das System neu gestartet wird.
quelle
Wenn Sie über eine Interprozesskommunikation verfügen, kann dies dazu führen, dass andere Prozesse je nach Protokoll niemals Ressourcen abschließen und verbrauchen.
Als Beispiel habe ich einmal mit dem Drucken auf einem PDF-Drucker in Java experimentiert, als ich die JVM mitten in einem Druckerauftrag beendet habe, der PDF-Spooling-Prozess aktiv blieb und ich ihn im Task-Manager beenden musste, bevor ich konnte Wiederholen Sie den Druck.
quelle