Wird der mallocierte Speicher automatisch freigegeben, wenn Sie eine C-Anwendung beenden?

Lesezeit: 9 Minuten

Nehmen wir an, ich habe den folgenden C-Code:

int main () {
  int *p = malloc(10 * sizeof *p);
  *p = 42;
  return 0;  //Exiting without freeing the allocated memory
}

Wenn ich dieses C-Programm kompiliere und ausführe, dh nachdem ich etwas Speicherplatz zugewiesen habe, wird dieser Speicher, den ich zugewiesen habe, immer noch zugewiesen (dh er nimmt im Grunde genommen Speicherplatz ein), nachdem ich die Anwendung beendet habe und der Prozess beendet ist?

  • Es ist “guter Stil”, Ihren Speicher zu bereinigen, nicht weil Sie möglicherweise auf einem Betriebssystem laufen, das keinen geschützten Speicher hat (was der Hauptvorschlag unten ist), sondern weil es die Wahrscheinlichkeit erhöht, dass Sie Speicherlecks finden und behalten Ihr Code schlank und korrekt …

    – Matt Tischler

    6. Februar 2010 um 16:42 Uhr

  • Ich weiß, dass es nicht wirklich wichtig ist, da es nur ein Beispiel ist, aber warum Speicher für 10 zuweisen ints wenn Sie nur einen speichern?

    – Flarn2006

    1. Januar um 18:19 Uhr


Es hängt vom Betriebssystem ab. Die meisten modernen (und alle wichtigen) Betriebssysteme geben Speicher frei, der nicht vom Programm freigegeben wurde, wenn es endet.

Sich darauf zu verlassen, ist eine schlechte Praxis und es ist besser, es explizit freizugeben. Das Problem ist nicht nur, dass Ihr Code schlecht aussieht. Vielleicht möchten Sie Ihr kleines Programm in ein größeres, lang laufendes integrieren. Dann müssen Sie eine Weile später Stunden damit verbringen, Speicherlecks aufzuspüren.
Das Verlassen auf eine Funktion eines Betriebssystems macht den Code auch weniger portabel.

  • Ich bin win98 einmal auf einer eingebetteten Plattform begegnet, und basierend auf dieser Erfahrung kann ich sagen, dass es KEINEN Speicher freigibt, wenn Programme geschlossen werden.

    – San Jacinto

    6. Februar 2010 um 15:44 Uhr

  • @Ken Es war ein Beispiel. Außerdem gibt es eine Grenze zwischen YAGNI und schlampiger Codierung. Ressourcen nicht freizugeben geht darüber hinaus. Das YAGNI-Prinzip sollte auch auf Funktionen angewendet werden, nicht auf Code, der dafür sorgt, dass das Programm korrekt funktioniert. (Und Speicher nicht freizugeben ist ein Fehler).

    – Yacoby

    6. Februar 2010 um 15:53 ​​Uhr

  • +1: Das Wichtigste ist, dass die Speicherverwaltung so ist, wie Yacoby ganz richtig sagt: „ein Merkmal des Betriebssystems“. Wenn ich mich nicht irre, definiert die Programmiersprache nicht, was vor oder nach der Programmausführung passiert.

    – D. Shawley

    6. Februar 2010 um 15:57 Uhr

  • Das manuelle Freigeben von Speicher nimmt mehr Zeit in Anspruch, benötigt mehr Code und führt zu der Möglichkeit von Fehlern (sagen Sie mir, dass Sie noch nie einen Fehler im Freigabecode gesehen haben!). Es ist nicht “schludrig”, etwas absichtlich wegzulassen, was für Ihren speziellen Anwendungsfall in jeder Hinsicht schlechter ist. Wenn Sie es nicht auf einem alten / winzigen System ausführen möchten, das nach der Beendigung des Prozesses keine Seiten freigeben kann, oder es in ein größeres Programm (YAGNI) integrieren, sieht es für mich wie ein Nettoverlust aus. Ich weiß, dass es das Ego eines Programmierers verletzt, daran zu denken, es nicht selbst aufzuräumen, aber auf welche praktische Weise ist es tatsächlich besser?

    – Ken

    6. Februar 2010 um 16:56 Uhr

  • Jeder, der Speicherlecks auf SO vorschlägt, sollte aller Reputation und Abzeichen beraubt werden

    – Ulterior

    17. Mai 2012 um 21:38 Uhr

Benutzeravatar von Kevin Reid
Kevin Reid

Im Algemeinen, Moderne Allzweck-Betriebssysteme bereinigen nach beendeten Prozessen. Dies ist notwendig, weil die Alternative darin besteht, dass das System im Laufe der Zeit Ressourcen verliert und einen Neustart erfordert, weil Programme schlecht geschrieben sind oder einfach nur selten auftretende Fehler aufweisen, die Ressourcen verlieren.

Es kann eine gute Praxis sein, wenn Ihr Programm seine Ressourcen trotzdem explizit freigibt aus verschiedenen Gründen, wie z.

  • Wenn Sie zusätzliche Ressourcen haben, die sind nicht vom Betriebssystem beim Beenden bereinigt werden, z. B. temporäre Dateien oder andere Rückgeld an den Zustand einer externen Ressource, dann benötigen Sie Code, um all diese Dinge beim Beenden zu handhaben, und dies wird oft elegant mit dem Freigeben von Speicher kombiniert.
  • Wenn Ihr Programm eine längere Lebensdauer hat, werden Sie das nicht wollen nur Möglichkeit, Speicher freizugeben, um zu beenden. Beispielsweise möchten Sie vielleicht Ihr Programm in einen Server (Daemon) umwandeln, der weiterläuft, während er viele Anforderungen für einzelne Arbeitseinheiten verarbeitet, oder Ihr Programm könnte ein kleiner Teil eines größeren Programms werden.

Hier ist jedoch ein Grund, die Speicherfreigabe zu überspringen: effizientes Herunterfahren. Angenommen, Ihre Anwendung enthält einen großen Cache im Arbeitsspeicher. Wenn es beim Beenden die gesamte Cache-Struktur durchläuft und Stück für Stück freigibt, dient das keinem nützlichen Zweck und verschwendet Ressourcen. Betrachten Sie insbesondere den Fall, in dem die Speicherseiten, die Ihren Cache enthalten, vom Betriebssystem auf die Festplatte ausgelagert wurden; Indem du die Struktur begehst und sie befreist, bist du all diese Seiten auf einmal wieder in Erinnerung zu bringenwodurch viel Zeit und Energie ohne wirklichen Nutzen verschwendet werden und möglicherweise sogar dazu führen, dass andere Programme auf dem System ausgetauscht werden!

Als verwandtes Beispiel gibt es Hochleistungsserver, die so arbeiten, dass sie für jede Anfrage einen Prozess erstellen und ihn dann beenden, wenn er fertig ist; Auf diese Weise müssen sie nicht einmal das Gedächtnis verfolgen Zuweisung, und führen Sie niemals eine Freigabe oder Garbage Collection durch, da am Ende des Prozesses alles einfach wieder im freien Speicher des Betriebssystems verschwindet. (Dasselbe kann innerhalb eines Prozesses mit einem benutzerdefinierten Speicherzuordner durchgeführt werden, erfordert jedoch eine sehr sorgfältige Programmierung; im Wesentlichen muss man seine eigene Vorstellung von „leichtgewichtigen Prozessen“ innerhalb des Betriebssystemprozesses entwickeln.)

Benutzeravatar von Wes Miller
Wes Miller

Ich entschuldige mich dafür, dass ich so lange nach dem letzten Beitrag zu diesem Thread gepostet habe.

Ein zusätzlicher Punkt. Nicht alle Programme schaffen es zu eleganten Exits. Abstürze und Strg-C usw. führen dazu, dass ein Programm auf unkontrollierte Weise beendet wird. Wenn Ihr Betriebssystem Ihren Heap nicht freigibt, Ihren Stack nicht bereinigt, statische Variablen löscht usw., würden Sie Ihr System schließlich aufgrund von Speicherlecks oder Schlimmerem zum Absturz bringen.

Abgesehen davon ist interessant, dass Abstürze/Unterbrechungen in Ubuntu und ich vermute, dass alle anderen modernen Betriebssysteme Probleme mit “verwalteten” Ressourcen haben. Sockets, Dateien, Geräte usw. können “geöffnet” bleiben, wenn ein Programm endet/abstürzt. Das ist es Es ist auch eine gute Übung, alles mit einem “Handle” oder “Deskriptor” als Teil Ihrer Reinigung vor dem ordnungsgemäßen Verlassen zu schließen.

Ich entwickle derzeit ein Programm, das stark Sockets verwendet. Wenn ich in einem Hang stecke, muss ich ctrl-c aus ihm herauskommen, wodurch meine Sockets gestrandet sind. Ich habe einen std::vector hinzugefügt, um eine Liste aller geöffneten Sockets und einen Sigaction-Handler zu sammeln, der Sigint und Sigterm abfängt. Der Handler geht die Liste durch und schließt die Sockets. Ich plane, eine ähnliche Bereinigungsroutine für die Verwendung vor Throws zu erstellen, die zu einer vorzeitigen Beendigung führen wird.

Möchte jemand etwas zu diesem Design sagen?

  • Ich bin froh, dass Sie das gesagt haben, denn ich hatte ein Programm, das Socket-Ressourcen übrig ließ, und unser Ubuntu-System musste alle zwei Wochen neu gestartet werden, oder der Speicher ging zur Neige, und es ist viel Speicher vorhanden. Ich bin mir nicht sicher, ob Systemressourcen abgebaut werden, wenn Sie vergessen, sie zu bereinigen.

    – Krakengrabbus

    8. Juli 2012 um 21:29 Uhr

  • Stackoverflow ist kein Forum; Es gibt nichts falsch mit der Beantwortung einer alten Frage. meta.stackexchange.com/questions/20524/reviving-old-questions

    – mk12

    16. August 2012 um 1:45 Uhr


Was passiert hier (in einem modernen Betriebssystem) besteht darin, dass Ihr Programm in einem eigenen “Prozess” ausgeführt wird. Dies ist eine Betriebssystemeinheit, die mit einem eigenen Adressraum, Dateideskriptoren usw. ausgestattet ist malloc Aufrufe weisen Speicher aus dem “Heap” oder nicht zugewiesenen Speicherseiten zu, die Ihrem Prozess zugewiesen sind.

Wenn Ihr Programm wie in diesem Beispiel endet, werden alle Ihrem Prozess zugewiesenen Ressourcen vom Betriebssystem einfach recycelt/abgebaut. Beim Arbeitsspeicher werden alle Ihnen zugewiesenen Speicherseiten einfach als „frei“ markiert und für die Nutzung durch andere Prozesse wiederverwendet. Seiten sind ein Konzept auf niedrigerer Ebene als das, was malloc handhabt – daher werden die Besonderheiten von malloc/free einfach weggespült, wenn das Ganze aufgeräumt wird.

Es ist das moralische Äquivalent dazu, dass Sie sich nicht die Mühe machen, jede Datei einzeln zu löschen, wenn Sie mit der Verwendung Ihres Laptops fertig sind und ihn einem Freund geben möchten. Sie formatieren nur die Festplatte.

All dies gesagt, wie alle anderen Antwortenden anmerken, ist es keine gute Praxis, sich darauf zu verlassen:

  1. Sie sollten immer so programmieren, dass Sie sich um Ressourcen kümmern, und in C bedeutet das auch Speicher. Sie könnten Ihren Code am Ende in eine Bibliothek einbetten, oder er könnte am Ende viel länger laufen als erwartet.
  2. Einige Betriebssysteme (ältere und möglicherweise einige moderne eingebettete) halten solche harten Prozessgrenzen möglicherweise nicht ein, und Ihre Zuweisungen können sich auf die Adressräume anderer auswirken.

Benutzeravatar von Mark Wilkins
Markus Wilkins

Ja. Das Betriebssystem bereinigt Ressourcen. Nun … alte Versionen von NetWare nicht.

Bearbeiten: Wie San Jacinto betonte, gibt es sicherlich Systeme (abgesehen von NetWare), die das nicht tun. Sogar in Wegwerfprogrammen versuche ich, es mir zur Gewohnheit zu machen, alle Ressourcen freizusetzen, nur um die Gewohnheit aufrechtzuerhalten.

  • Ich stimme nicht ab, aber dies ist ein ziemlich gefährlicher Beitrag für die Nachwelt. DOS wird immer noch auf vielen eingebetteten Plattformen verwendet, und ich bezweifle ernsthaft, dass es die Speicherbereinigung für Sie übernimmt. Die pauschale Verallgemeinerung ist falsch.

    – San Jacinto

    6. Februar 2010 um 15:54 Uhr

  • @San Jacinto: Das ist ein guter Punkt. Aus diesem Grund habe ich die NetWare-Referenz erstellt, aber sie könnte wahrscheinlich eine Klarstellung gebrauchen. Ich werde es ein wenig bearbeiten.

    – Mark Wilkins

    6. Februar 2010 um 16:15 Uhr

  • @San DOS ist kein Multitasking-Betriebssystem – wenn ein DOS-Programm (außer TSRs) endet, steht der gesamte Speicher für das nächste zu ladende Programm zur Verfügung.

    anon

    6. Februar 2010 um 16:22 Uhr

  • @Neil danke für die Erinnerung, aber ich bezog mich auf ein TSR-ähnliches Programm, das gestartet wird, wenn ein Ereignis eintritt, wie es für eingebettete Systeme üblich ist. Trotzdem vielen Dank für Ihre Expertise und Klärung, wo ich versagt habe 🙂

    – San Jacinto

    6. Februar 2010 um 16:32 Uhr

Benutzeravatar von Draemon
Draemon

Ja, das Betriebssystem gibt den gesamten Speicher frei, wenn der Prozess endet.

  • Ich stimme nicht ab, aber dies ist ein ziemlich gefährlicher Beitrag für die Nachwelt. DOS wird immer noch auf vielen eingebetteten Plattformen verwendet, und ich bezweifle ernsthaft, dass es die Speicherbereinigung für Sie übernimmt. Die pauschale Verallgemeinerung ist falsch.

    – San Jacinto

    6. Februar 2010 um 15:54 Uhr

  • @San Jacinto: Das ist ein guter Punkt. Aus diesem Grund habe ich die NetWare-Referenz erstellt, aber sie könnte wahrscheinlich eine Klarstellung gebrauchen. Ich werde es ein wenig bearbeiten.

    – Mark Wilkins

    6. Februar 2010 um 16:15 Uhr

  • @San DOS ist kein Multitasking-Betriebssystem – wenn ein DOS-Programm (außer TSRs) endet, steht der gesamte Speicher für das nächste zu ladende Programm zur Verfügung.

    anon

    6. Februar 2010 um 16:22 Uhr

  • @Neil danke für die Erinnerung, aber ich bezog mich auf ein TSR-ähnliches Programm, das gestartet wird, wenn ein Ereignis eintritt, wie es für eingebettete Systeme üblich ist. Trotzdem vielen Dank für Ihre Expertise und Klärung, wo ich versagt habe 🙂

    – San Jacinto

    6. Februar 2010 um 16:32 Uhr

Benutzeravatar von Charles
Karl

Es hängt davon ab, dass Betriebssysteme es normalerweise für Sie bereinigen, aber wenn Sie beispielsweise an eingebetteter Software arbeiten, wird sie möglicherweise nicht veröffentlicht.

Stellen Sie einfach sicher, dass Sie es freigeben, es kann Ihnen später viel Zeit sparen, wenn Sie es in ein großes Projekt integrieren möchten.

1421970cookie-checkWird der mallocierte Speicher automatisch freigegeben, wenn Sie eine C-Anwendung beenden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy