Sollte ich mir die Mühe erkennen OOM (out of memory) Fehler in meinem C-code?
Habe ich gewidmet, eine große Anzahl von Zeilen C-code cleanup-Etiketten/Bedingungen für fehlgeschlagene memory allocation (angedeutet durch die alloc
Familie zurückkehren NULL
). Ich wurde gelehrt, dass dies war eine gute übung, so dass auf die memory-Fehler, wird eine entsprechende Fehler-status konnte markiert werden und der Anrufer könnte möglicherweise dazu führen "anmutig Speicher bereinigen" und "wiederholen". Ich habe jetzt einige Zweifel über diese Philosophie, dass ich bin der Hoffnung, zu klären.
Ich denke, es ist möglich, dass ein Anrufer könnte deallocate übermäßige Pufferspeicher oder strip-relationale Objekte Ihrer Daten, aber finde ich das der Anrufer nur selten die Möglichkeit hat, (oder ist auf der entsprechenden Ebene der Abstraktion) zu tun. Auch, frühen Rückkehr aus der aufgerufenen Funktion ohne Nebenwirkungen ist oft nicht trivial.
Ich auch gerade entdeckt, das Linux OOM-killer, der scheint, um diese Bemühungen völlig sinnlos auf meine primäre Entwicklungs-Plattform.
Linux standardmäßig folgt ein
optimistisch memory-allocation-Strategie.
Dies bedeutet, dass beim malloc() gibt
nicht-NULL-es gibt keine Garantie, dass
der Speicher wirklich verfügbar ist.
Das ist ein wirklich schlechter Fehler. Falls es
stellt sich heraus, dass das system aus
Speicher, einen oder mehrere Prozesse
werden getötet von der berüchtigten OOM
killer.
Ich vermute, es gibt wahrscheinlich auch andere Plattformen gibt, die nach dem gleichen Prinzip. Ist es etwas pragmatisch, das macht die überprüfung für die OOM Bedingungen lohnt?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Out-of-memory Bedingungen, kann passieren, auch auf modernen Rechnern mit viel Arbeitsspeicher, wenn das Benutzer-oder system-administrator beschränkt (siehe ulimit) mit dem Speicher für einen Prozess oder das Betriebssystem unterstützt memory allocation limits pro Benutzer. In pathologischen Fällen, die Fragmentierung macht das ziemlich wahrscheinlich, sogar.
Jedoch, da die Verwendung von dynamisch allokierten Speichers ist weit verbreitet in der modernen Programme, mit guten Gründen, wird es sehr haarig handle out-of-memory-Fehler. Prüfung und Umgang mit Fehlern dieser Art würde müssen gemacht werden, überall, bei hohen Kosten der Komplexität.
Ich finde, dass es besser ist, die Gestaltung des Programms, so dass es zum Absturz zu jeder Zeit. Zum Beispiel, stellen Sie sicher, dass die Daten die der Benutzer erstellt hat bekommt auf der Festplatte gespeichert, sogar dann, wenn der Benutzer nicht explizit speichern. (Siehe vi -r, zum Beispiel.) Auf diese Weise können Sie eine Funktion erstellen, um Speicher zuzuweisen, der beendet das Programm, wenn ein Fehler aufgetreten ist. Da Ihre Anwendung ist entworfen, um Abstürze zu jeder Zeit, es ist OK, zum Absturz zu bringen. Der Benutzer wird überrascht sein, aber nicht verlieren (viel) Arbeit.
Den nie versagenden Zuordnung Funktion könnte in etwa so (ungetestet, unkompilierte code, nur zu Demonstrationszwecken):
Valerie Aurora Artikel Crash-only-software könnte erhellend sein.
Blick auf die andere Seite der Frage: wenn du malloc Speicher, es schlägt fehl, und Sie nicht erkennen es an der malloc, wenn wird Sie erkennen es?
Offensichtlich, wenn Sie versuchen, dereferenzieren Sie die Zeiger.
Wie erkennen Sie es? Durch eine
Bus error
oder etwas ähnliches, irgendwo nach dem malloc, dass müssen Sie die Spur mit einem core-dump in den debugger.Auf der anderen Seite, können Sie schreiben
bekommen und "OOM im parser.c:447".
Ihnen abgeholt.
Update
Gute Frage, über anmutig zurück. Die Schwierigkeit bei der Sicherstellung eine anmutige Rückkehr ist, dass Sie in der Regel wirklich nicht festlegen können, bis zu einem Paradigma oder Muster, wie Sie tun, dass, vor allem in C, das ist immerhin ein schickes assembly-Sprache. In ein garbage Collection-Umgebung, könnte man die Kraft auf einen Tisch; in einer Sprache, mit Ausnahmen, kann man eine Ausnahme werfen, und entspannen Sie sich Dinge. In C haben Sie es selbst zu tun und so müssen Sie entscheiden, wie viel Mühe Sie setzen in es.
In die meisten Programme, abnormal zu beenden, ist über die beste Sie tun können. In diesem Schema werden Sie (hoffentlich) bekommen eine brauchbare Fehlermeldung auf stderr -- natürlich könnte es auch sein, um einen logger oder sowas -- und einen bekannten Wert als Rückgabe-code.
Hohe Zuverlässigkeit Programme mit kurzen recovery-Zeiten schieben Sie Sie in etwas wie recovery blocks, wo Sie code schreiben, der versucht, um ein system wieder in einen ausfallsicheren Zustand. Diese sind groß, aber kompliziert; das Papier, das ich verlinkt spricht über Sie im detail.
In der Mitte, können Sie kommen mit einer mehr komplizierten Speicher-management-Schema, sagen wir verwalten Ihren eigenen pool dynamischer Speicher -- nach allem, wenn jemand anderes schreiben können, malloc, so können Sie.
Aber es gibt einfach kein Allgemeines Muster (von denen ich bin mir bewusst, trotzdem) für die Reinigung bis genug zurückkehren können zuverlässig und lassen Sie die Umgebung Programm weiter.
Unabhängig von der Plattform (vielleicht mit Ausnahme der embedded-Systeme) ist es eine gute Idee zu überprüfen, für
NULL
und dann einfach verlassen ohne (oder viel) Bereinigung von hand.Out of memory ist nicht ein einfacher Fehler. Es ist eine Katastrophe, die auf heutigen Systemen.
Buch Die Praxis der Programmierung (Brian W. Kernighan und Rob Pike, 1999) definiert Funktionen wie
emalloc()
die nur beendet sich mit einer Fehlermeldung, wenn es keinen Speicher mehr.emalloc
für Verhaltensweisen, die relevant für Ihre Plattform. Zum Beispiel, eine unendliche Schleife statt einerexit
anrufen, wenn Sie kein Betriebssystem auf einem mikrocontroller.Es hängt davon ab, was du schreibst. Ist es ein Allzweck-Bibliothek? Wenn ja, möchten Sie den Umgang mit einem Mangel an Speicher so würdevoll wie möglich, insbesondere, wenn es ist vernünftig, zu erwarten, dass es verwendet wird, die auf el-cheapo-Systeme oder embedded-Geräte.
Bedenken Sie: ein Programmierer ist mit Ihrer Bibliothek. Es ist ein bug (uninitialised variables vielleicht) in seinem Programm, der vergeht, ein dummes argument, um Ihren code, die damit versucht zu vergeben, single 3,6 GB Speicherblock. Offensichtlich
malloc()
NULL zurück. Würde er eher eine unerklärliche segfault erzeugt, die irgendwo in der Bibliothek-code, oder eine return-Wert um den Fehler anzuzeigen?Um zu vermeiden, dass Fehler prüft alle über Ihren code ein Ansatz ist die Verteilung der angemessenen Mengen von Arbeitsspeicher an den start, und sub-reservieren Sie es.
In Bezug auf die Linux OOM-killer, ich habe gehört, dass dieses Verhalten ist nun standardmäßig deaktiviert major-Distributionen. Auch wenn es aktiviert ist, nicht bekommen, die falsche Idee:
malloc()
kann NULL zurück, und es wird sicherlich, wenn Ihr Programm den gesamten Speicher verwenden, übertreffen würde, 4GiB (auf einem 32-bit-system). In anderen Worten, selbst wennmalloc()
nicht wirklich sicher Sie einige RAM/swap-Speicher, es wird behält sich vor, Teil Ihres Adressraums.Schlage ich vor, ein experiment - schreiben Sie ein kleines Programm, das hält allokierung von Speicher ohne Freigabe und druckt anschließend eine kleine (fest -) Meldung, wenn die Allokation fehlschlägt. Welche Auswirkungen bemerken Sie auf Ihrem system, wenn Sie dieses Programm ausführen? Bedeutet die Meldung, die jemals gedruckt werden?
Wenn das system verhält sich normal und bleibt reaktionsschnell Weg bis zu dem Punkt, wenn der Fehler angezeigt wird, dann würde ich sagen ja, es lohnt. OTOH, wenn das system langsam, nicht reagiert, und eventaually unbrauchbar, bevor die Meldung angezeigt wird (wenn überhaupt) dann ich würde ich sagen, Nein, es ist nicht lohnt.
Wichtig: Bevor Sie diesen test durchführen, speichern Sie alle wichtige Arbeit. Führen Sie es nicht auf einem Produktions-server.
Regardfing die Linux OOM behaviur - dies ist eigentlich wünschenswert und ist die Art und Weise, dass die meisten OSs-Arbeit. Es ist wichtig zu wissen, dass wenn Sie malloc() Speicher, Sie sind NICHT immer direkt von der OS, die Sie bekommen es von der C-Laufzeit-Bibliothek. Dies wird in der Regel gebeten haben, das OS für einen großen Teil des Speicher vorne (oder bei der ersten Anfrage), die es dann schafft es über malloc/free-Schnittstelle. Wie viele Programme verwenden Sie niemals dynamiic Erinnerung an alle, es wäre nicht wünschenswert für die OS in der hand "echter" Speicher an die C-Laufzeit - statt die Hände som euncomitted vM, die eigentlich comitted, wie Sie Ihren malloc-Aufrufe.
Mit den heutigen Computern und die Menge an RAM in der Regel installiert ist, überprüfen überall für memory allocation Fehler ist vermutlich zu detailliert. Wie Sie gesehen haben, ist es oft schwierig oder unmöglich, eine rationale Entscheidung darüber, was zu freigeben. Als Ihr Prozess wird dadurch mehr und mehr Speicher, das Betriebssystem wird entsprechend werden, die Verringerung der Menge an Speicherplatz für disk-Puffer. Wenn, dass fällt unter eine bestimmte Schwelle, dann wird das OS starten paging-Speicher auf die Festplatte. (Dies ist eine Vereinfachung, denn es gibt viele Faktoren, die in-memory-management).
Sobald das OS startet, Auslagerung von Arbeitsspeicher, das ganze system wird immer langsamer und langsamer, und es wird wohl noch eine ganze Weile dauern, bevor die Anwendung überhaupt wirklich sieht NULL von malloc (wenn überhaupt).
Mit der schieren Menge der verfügbaren Speicher auf heutigen Systemen, ein "out of memory" Fehler mehr wahrscheinlich bedeutet, dass ein Fehler in Ihrem code tried to allocate eine beliebige Menge von Speicher. In diesem Fall wird kein Betrag der Befreiung und erneuter Versuch auf den Teil des Prozesses geht, um das problem zu beheben.
Müssen Sie abwägen, was besser oder schlechter für Sie: die Umsetzung all der Arbeit, in Prüfung für die OOM oder mit Ihrem Programm scheitern zu unerwarteten Zeiten
Prozesse sind in der Regel mit einem limit der Ressourcen (siehe ulimit (3)) auf den stack-Größe, aber nicht auf den heap-Größe. malloc (3) wird die Speicherverwaltung Anstieg der heap-Bereich Seite-durch-Seite aus dem Betriebssystem, und das Betriebssystem veranlasst, diese Seite irgendwie zugeteilt, die körperlich und entsprechen heap für Ihren Prozess. Wenn es nicht mehr RAM in Ihrem computer, dann die meisten Betriebssysteme hat so etwas wie eine swap-partition auf der DVD. Wenn Ihr system beginnt zu müssen, tauschen dann die Dinge allmählich zu langsam. Wenn ein Prozess, führt zu diesem, kann es leicht identifiziert werden mit einem Dienstprogramm wie ps (1).
Sei denn, Ihr code wird ausgeführt mit einer Ressource beschränken, oder auf einem system mit arm Größe der Speicher und kein swap, ich denke, man kann das Programm mit der Annahme, dass malloc (3) erfolgreich. Wenn Sie nicht sicher sind, stellen Sie einfach ein dummy-wrapper, der vielleicht eines Tages tun, den check-in und verlassen Sie einfach. Ein Fehler-status return-Wert nicht sinnvoll ist, da Ihr Programm erfordert der Speicher schon reserviert hat. Wenn Ihr malloc (3) schlägt fehl, und Sie nicht auf NULL prüfen, Ihre Prozess wird sowieso sterben, wenn es beginnt, Zugriff auf die (NULL -) Zeiger hat es.
Probleme mit malloc (3) ist in den meisten Fällen nicht auftreten von out-of-memory, aber von einem logischen Fehler im Programm, der dazu führt, fehlerhaftes Aufrufe von malloc und free. Das übliche problem wird nicht erkannt durch die überprüfung malloc Erfolg.
Gut. Hängt alles von der situation.
Erste von allen. Wenn Sie haben festgestellt, ein Speicher ist unausreichend für Ihren Bedarf - was werden Sie tun? Die häufigste Verwendung ist:
Gut. Auch wenn es nicht mit malloc kann es zuordnen, die Puffer. Zusätzlich wird auch schlecht, wenn es eine GUI-Anwendung - Ihr Benutzer ist unwahrscheinlich, dass es vor Ort. Wenn Ihr Benutzer schlau genug", um starten Sie die Applikation von der Konsole zum überprüfen Fehler wird er wohl sehen, dass etwas aß seiner gesamten Speicher. Ok. So kann ein dialog? Aber anzeigen kann das Dialogfeld aß Ressourcen - und meistens wird.
Zweitens - warum brauchen Sie die Informationen über die OOM? Es passiert in zwei Fällen:
Ja, ich glaube, es ist, wenn Sie Folgen Sie den Praxis konsequent. Dies ist möglicherweise unpraktisch, für ein großes Programm in C geschrieben, weil der Grad der Arbeitskraft, dies kann erfordern, aber in einer modernen Sprache, die die meiste Arbeit für Sie erledigt ist, weil eine out-of-memory-Bedingung führt dazu, dass eine Ausnahme geworfen.
Vorteile dies zu tun, konsequent sind, dass das Programm nicht in einem undefinierten Zustand aufgrund der out-of-memory-Bedingung, wodurch ein Pufferüberlauf (dies lässt die Möglichkeit offen, einen nicht definierten Zustand durch ein vorzeitiges verlassen der Funktion, das ist zwar eine andere Klasse von bug). Dass so getan, Ihr Programm konsequent behandelt die Fehlerbedingung, oder wenn der Fehler war kritisch, zu entscheiden, zu beenden, die in eine anmutige Art und Weise.
Prüfung für OOM Bedingungen und geeignete Maßnahmen ergreifen kann schwierig sein, wenn Sie misdesign software. Ob Sie wirklich überprüfen müssen, um vor solchen Situationen hängt die Zuverlässigkeit der software, die Sie möchten zu bekommen.
E. g. VirtualBox-hypervisor wird erkennen, out-of-memory-Fehlern und anmutig pause virtuellen Maschine, so dass Benutzer einige Anwendungen schließen, um Speicher freizugeben. Ich beobachtete ein solches Verhalten unter Windows. Eigentlich fast alle Anrufe in VirtualBox Erfolg haben-Indikator als Rückgabewert und Sie kann gerade zurück
VERR_NO_MEMORY
zu bezeichnen, die memory allocation failed". Dies führt einige zusätzliche Prüfungen, aber in diesem Fall ist es es Wert.