Speicherleck in C, C++; vergessen zu tun kostenlos, löschen

Lesezeit: 9 Minuten

Benutzeravatar von seg.server.fault
seg.server.fault

Wir weisen Speicher in C mit malloc und in C++ mit new zu. Ich weiß, dass der zugewiesene Speicher freigegeben oder an das Betriebssystem zurückgegeben werden muss, indem free in C und delete in C++ verwendet werden. Wenn ich nach der Speicherzuweisung vergessen habe, free/delete zu verwenden, bedeutet dies, dass es zu einem Speicherleck kommt.

Meine Frage ist nun, ob dieses Speicherleck nur während der Ausführung des Programms auftritt. oder ist es ein dauerhaftes Leck / Verlust oder wird es wieder gewonnen, wenn ich das System neu starte? Was ist eigentlich der interne Prozess? Was genau bedeutet Speicherleck/-verlust?

Ich wäre sehr dankbar, wenn jemand dies im Detail erklären könnte oder mir ein paar nette Referenzen geben könnte.

AKTUALISIERUNG 1

Nachdem ich einige Antworten gelesen hatte, erfuhr ich, dass Speicher nach dem Beenden des Programms an das Betriebssystem/System zurückgegeben wird. Wenn dies der Fall ist, warum muss sich jeder so sehr um Speicherlecks kümmern und warum ist es sehr wichtig, Speicherlecks zu verhindern?

AKTUALISIERUNG 2

Speicherlecks sollten also verhindert werden, damit das System nicht aufgrund von Speichermangel für Allokationszwecke abstürzt ??

AKTUALISIERUNG 3

Nachdem ich alle Antworten gelesen hatte, wurde mir klar, dass Speicherlecks sehr wichtige Probleme sind, um Systemabstürze zu verhindern. Aber wie kann ich für einen Anfänger wie mich sicher sein, dass mein Programm vollständig frei von Speicherlecks ist? Ich versuche, free,delete zu machen, wenn ich malloc,new benutze, aber manchmal wird es chaotisch. Gibt es ein Tool oder eine Methode, mit der ich feststellen kann, ob mein Programm ein Speicherleck verursacht?

UPDATE 4

Nachdem ich die Antworten gelesen habe, habe ich jetzt die Bedeutung von speicherleckfreiem Code verstanden, weniger Verwendung von Neu/Löschen, mehr Verwendung von STL, neue Dinge wie RAII, Valgrind und gute Programmierpraktiken gelernt. Dank an alle 🙂

  • Um Ihre zweite Bearbeitung zu beantworten, lesen Sie den zweiten Absatz in meiner Antwort

    – Brian Agnew

    5. August 2009 um 10:19 Uhr

Benutzeravatar von Brian Agnew
Brian Agnew

Es ist pro Prozess. Sobald Ihr Prozess beendet wird, wird der zugewiesene Speicher an das Betriebssystem zurückgegeben, damit er von anderen Prozessen (neuen oder vorhandenen) verwendet werden kann.

Um Ihre bearbeitete Frage zu beantworten, ist auf Ihrem Computer nur eine begrenzte Menge an Speicher vorhanden. Wenn Sie also ein Speicherleck haben, besteht das Hauptproblem darin, dass der Speicher nicht verfügbar ist Sonstiges Prozesse zu verwenden. Ein sekundärer, aber nicht zu vernachlässigender Effekt ist, dass Ihr Prozessabbild wächst, Sie auf Disc wechseln und die Leistung beeinträchtigt wird. Schließlich erschöpft Ihr Programm den gesamten Speicher im System und schlägt fehl, da es sich selbst keinen Speicher zuweisen kann.

Es lässt sich argumentieren, dass für einen kleinen Prozess mit kurzer Lebensdauer Speicherlecks tolerierbar sind, da der Speicherverlust nur eine geringe Menge und eine kurze Lebensdauer hat.

Schauen Sie sich an diese Ressource, für möglicherweise mehr Informationen, als Sie jemals benötigen werden. Worüber wir hier diskutieren, ist dynamisch oder Haufen Zuweisung.

  • Ich würde den Wortlaut ändern, um zu sagen, dass Speicherlecks tolerierbar sein könnten.

    – Lasse V. Karlsen

    5. August 2009 um 11:02 Uhr

  • Ich würde argumentieren, dass das Erträgliche im wirklichen Leben eine schlechte Entschuldigung für schlechte Programmierung ist. Speicherlecks verbergen oft andere Ressourcenprobleme. Auch wenn sich die Industrie hin zu servicebasierten Architekturen bewegt, werden kurzlebige Prozesse immer seltener, und die kurzlebigen Prozesse von heute werden plötzlich zu den kritischen, langlebigen Diensten von morgen.

    – Martin York

    5. August 2009 um 17:06 Uhr

  • Ich widerspreche nicht, dass dies eine schlechte Praxis und möglicherweise ein Problem in der Zukunft ist

    – Brian Agnew

    5. August 2009 um 18:36 Uhr

Ein Speicherleck bedeutet einfach das Ihre Bewerbung kann den zugewiesenen Speicher nicht freigeben. Sobald Ihr Programm endet, ist es Sache des Betriebssystems, was passiert. Jedes moderne Betriebssystem fordert den gesamten von der Anwendung verwendeten Speicher zurück, sodass Ihr Prozess nach Beendigung bereinigt wird.

Aber C/C++ nicht Garantie dass das Betriebssystem das tut. Auf einigen Plattformen ist es möglich, dass der Speicher bis zum Neustart verloren geht.

Das Problem mit Speicherlecks ist also zweierlei:

  • Auf einigen Plattformen muss das System möglicherweise neu gestartet werden, um den Arbeitsspeicher zurückzugewinnen. Auf den meisten Plattformen ist dies kein Problem, obwohl das Lecken einiger anderer Ressourcentypen immer noch Probleme verursachen kann.
  • Solange Ihr Programm läuft, weist es Speicher zu, den es nie freigibt, was bedeutet, dass es immer mehr Speicher verwendet. Wenn Ihr Programm für längere Zeit ausgeführt werden soll, kann es dazu führen, dass der gesamte verfügbare Speicher des Computers belegt wird und es anschließend abstürzt.

Viele kurz laufende Programme ignorieren tatsächlich Speicherlecks Weil Sie wissen, dass es bald genug vom Betriebssystem bereinigt wird. Soweit ich weiß, macht das der C++-Compiler von Microsoft. Sie wissen, dass der Compiler, sobald er aufgerufen wurde, höchstens ein paar Minuten läuft. (und sie wissen, dass es unter Windows läuft, wo das Betriebssystem tut Speicher zurückfordern, sobald der Prozess beendet ist) Es ist also in Ordnung, dass hier und da etwas Speicher verloren geht.

Erstellen Sie keine Speicherlecks, um Speicherlecks zu vermeiden.

Sie riskieren also jedes Mal, wenn Sie new/delete verwenden, Speicherverluste nicht.

Wenn Sie ein Array von Daten benötigen, tun Sie dies:

std::vector<char> vec(200);

an Stelle von:

char* arr = new char[200];

Ersteres ist genauso effizient, aber Sie müssen delete nicht explizit aufrufen, um es freizugeben std::vector verwendet RAII, um seine Ressourcen intern zu verwalten. Und Sie sollten das Gleiche tun – entweder indem Sie vorgefertigte RAII-Klassen wie verwenden vector, shared_ptroder fast jede andere Klasse in der Standardbibliothek oder in Boost, oder indem Sie Ihre eigene schreiben.

Als allgemeine Faustregel sollte Ihr Code keine new/delete-Aufrufe enthalten, außer im Konstruktor/Destruktor für die Klasse, die für die Verwaltung dieser Zuordnung verantwortlich ist.

Wenn ein Objekt den benötigten Speicher im Konstruktor zuweist und im Destruktor freigibt (und das Kopieren/Zuweisen korrekt handhabt), können Sie einfach eine lokale Instanz der Klasse auf dem Stapel erstellen, wann immer Sie sie benötigen, und das wird es nicht , kann nicht, Speicher auslaufen.

Der Schlüssel, um Speicher in C++ nicht zu verlieren, besteht darin, new/delete nicht aufzurufen.

  • Viele Leute sagen immer wieder, dass Sie immer ‘std::vector’ verwenden sollten, aber ich denke nicht, dass es ein so ‘kostenloses’ Mittagessen ist, wie jeder glauben möchte. Ja, ich stimme zu, Sie erhalten viele Vorteile, wie Sie sie beschreiben, aber std::iterator ist einfach nur zum Kotzen. Ich bin bei diesem Thema mit Andrei Alexandrescu zusammen – hier ist ein PDF von boost con über das Problem boostcon.com/site-media/var/sphene/sphwiki/attachment/2009/05/…

    – Zebrabox

    5. August 2009 um 10:46 Uhr

  • äh was? Alexandrescu sagte, dass C++ Bereiche unterstützen sollte, da sie potenziell einfacher und effizienter zu handhaben sein könnten als Iteratoren. Aber das hat nichts mit Vektor und nichts mit der Verwendung von Standardcontainern zu tun, um Speicherlecks zu verhindern. Ein wichtiger Punkt ist, dass er kein Anti-Iterator ist. Er weiß ganz genau, wie nützlich und mächtig sie sind. Sie sind viel besser als nicht Iteratoren haben. Er weist lediglich darauf hin, dass die Unterstützung von Bereichen eine weitere Verbesserung wäre. Was schlagen Sie also vor? Dass wir, bis sie Range-Support zu C++ hinzufügen, zu C zurückkehren sollten?

    – jalf

    5. August 2009 um 10:56 Uhr

  • In Ihrer Antwort geben Sie Beispiele in C++, um solche Speicherlücken in C zu vermeiden, würden Sie die Verwendung von empfehlen glatt Quelle: stackoverflow.com/questions/201413/c-analog-to-stl

    – Alan

    26. Januar 2016 um 11:20 Uhr

Das Betriebssystem verfolgt den Speicher und fordert nach Beendigung des Programms den gesamten Speicher zurück. Es bedeutet nur, dass Ihre Anwendung den Überblick über einen zugewiesenen Speicher verloren hat.

Beachten Sie, dass dies möglicherweise nicht auf einigen Betriebssystemen zutrifft, aber auf jedem System vom Typ Windows/Unix/Mac der Fall sein wird

  • Und denken Sie daran, dass es Auswirkungen auf andere laufende Programme haben kann, die abstürzen können, weil sie keinen Speicher zuweisen können!

    – mmmmmmmm

    5. August 2009 um 10:14 Uhr

  • Ich denke, Sie meinen jedes Windows-System mit 32 Bit oder höher oder jedes Mac-System mit OS X oder gängige nicht eingebettete Varianten von Unix …

    – Peter Kirkham

    10. November 2010 um 22:39 Uhr


Benutzeravatar von Shawn Chin
Shawn Chin

Betreff: Tools zum Erkennen von Speicherlecks

Wenn Sie ein Linux-basiertes Betriebssystem für die Entwicklung verwenden, können Sie versuchen, valgrind (http://valgrind.org/), um Speicherlecks zu erkennen.

valgrind --leak-check=full ./compiled_binary

Wenn Ihr Programm mit Debug-Symbolen kompiliert wurde (z. B. für gcc, fügen Sie das Flag -g hinzu), informiert Sie valgrind auch über die genaue Codezeile, in der der durchgesickerte Speicher zugewiesen wurde. Dies erleichtert die Aufgabe, Lecks zu verfolgen und zu beheben, erheblich.

Vorteile: Es ist kostenlos

Nachteile: AFAIK, es funktioniert nur unter Linux

Aktualisieren

Wie gesehen bei http://valgrind.org/info/platforms.htmlValgrind wird auf andere Betriebssysteme (und Plattformen) portiert, darunter MacOSX, FreeBSD und NetBSD.

Aktualisierung 2

(leicht off-topic aber…)

Das Gute an der Verwendung von valgrind ist, dass es viel mehr tut, als nur nach Speicherlecks zu suchen. Sehen http://valgrind.org/info/tools.html

Ich habe den Buildbot so konfiguriert, dass er Valgrind (und Splint) gegen alle meine nächtlichen Builds ausführt, und das hat sich als unschätzbar erwiesen!

Es gibt Tools, um Speicherlecks zu erkennen, z Reinigen.

Benutzeravatar von John Deters
John Deter

Als C++-Programmierneuling wäre der beste Rat, den ich Ihnen geben könnte, zu lernen, wie Sie die Anzahl der von Ihnen geschriebenen “new”- und “delete”-Anweisungen minimieren können. Wenn Sie den Compiler Ihre Objekte lokal auf dem Stack erstellen lassen, verwaltet er den Speicher für Sie und löscht die Objekte automatisch, wenn sie den Gültigkeitsbereich verlassen.

Es gibt eine Programmieridee namens Resource Acquisition Is Initialization (RAII). Was dies besagt, ist: „Wenn Sie Speicher zuweisen müssen, der gelöscht werden muss, oder sicherstellen müssen, dass Dinge, die Sie öffnen, geschlossen werden, packen Sie sie in ein Objekt, das Sie auf dem Stapel erstellen. Auf diese Weise wird der Destruktor verwendet, wenn das Objekt den Gültigkeitsbereich verlässt automatisch aufgerufen und Sie löschen Ihre Ressource im Destruktor.”

Häufige Speicherlecks treten auf, wenn Sie ein “new” in den Code schreiben, Ihre Funktion jedoch beendet wird, bevor Sie delete aufrufen. Manchmal stoßen Sie zu früh auf eine „return“-Anweisung, manchmal wird eine Ausnahme ausgelöst und nach Ihrer „delete“-Anweisung abgefangen. Wenn Sie RAII befolgen, können Sie sicherstellen, dass solche Unfälle nicht passieren.

Benutzeravatar von Mike McQuaid
Mike McQuaid

Es ist ein Speicherleck.

Im Grunde bedeutet dies, dass dieser Speicher nicht zurückgefordert wird, bis der Prozess zerstört ist.

Das Problem ist, wenn der Zeiger den Gültigkeitsbereich verlässt und Sie den Speicher nicht freigeben, dann wird er vom Prozess zugewiesen, aber das Programm kann nicht wissen, dass er sich außerhalb des Gültigkeitsbereichs befindet und nicht mehr benötigt wird (ohne ein Tool wie Valgrind).

Dies ist nur dann ein großes Problem, wenn es wiederholt vorkommt. Wenn dies der Fall ist, verbraucht das Programm mit zunehmender Laufzeit immer mehr Speicher, bevor es schließlich abstürzt. Benutzer müssen die Anwendung regelmäßig neu starten, um zu vermeiden, dass dies passiert oder zu viele Systemressourcen verwendet werden.

1403530cookie-checkSpeicherleck in C, C++; vergessen zu tun kostenlos, löschen

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

Privacy policy