7 Stimmen

Was sind Out-of-Memory-Strategien in der C-Programmierung?

Eine Strategie, die mir selbst eingefallen ist, besteht darin, beim Programmstart 5 Megabyte Speicher (oder eine beliebige Zahl, die Sie für notwendig halten) zuzuweisen.

Wenn das Programm an einem beliebigen Punkt malloc() gibt zurück. NULL geben Sie die 5 Megabyte frei und rufen malloc() erneut, was zum Erfolg führt und das Programm weiterlaufen lässt.

Was halten Sie von dieser Strategie?

Und welche anderen Strategien kennen Sie?

Danke, Boda Cydo.

1voto

EvilTeach Punkte 27313

Der Zweck der Freigabe des Speichers besteht im Allgemeinen darin, dass Sie genügend Speicher haben, um den Fehler zu melden, bevor Sie das Programm beenden.

Wenn Sie einfach weiterlaufen wollen, macht es keinen Sinn, die Notreserve im Voraus zuzuweisen.

1voto

blaze Punkte 4216

Die meisten modernen Betriebssysteme erlauben in der Standardkonfiguration eine Speicherüberbindung, so dass Ihr Programm von malloc() überhaupt keinen NULL-Wert erhält oder zumindest solange nicht, bis es irgendwie (durch einen Fehler, nehme ich an) den gesamten verfügbaren Adressraum (nicht den Speicher) ausgeschöpft hat. Und dann schreibt es eine völlig legale Speicherstelle, bekommt einen Page Fault, es gibt keine Speicherseite im Backing Store und BANG (SIGBUS) - Sie sind tot, und es gibt keinen guten Ausweg.

Vergessen Sie es einfach, Sie können damit nicht umgehen.

1voto

Hans Passant Punkte 894572

Ja, das funktioniert in der Praxis nicht. Erstens aus einem technischen Grund: Eine typische Heap-Implementierung mit geringer Fragmentierung stellt keine großen freien Blöcke für kleine Zuweisungen zur Verfügung.

Aber das eigentliche Problem ist, dass Sie nicht wissen por qué Ihnen der virtuelle Speicherplatz ausgegangen ist. Und wenn Sie nicht wissen, warum, dann können Sie nichts tun, um zu verhindern, dass dieser zusätzliche Speicher sehr schnell verbraucht wird und immer noch Ihr Programm mit OOM zum Absturz bringen. Das ist sehr wahrscheinlich, denn Sie haben bereits fast zwei Gigabyte verbraucht, die zusätzlichen 5 MB sind ein Tropfen Wasser auf einer heißen Platte.

Jede Art von Schema, das die App in den "Notfallmodus" versetzt, ist sehr unpraktisch. Sie müssen laufenden Code abbrechen, um beispielsweise das Laden einer riesigen Datendatei zu stoppen. Das erfordert eine Ausnahme. Jetzt sind Sie wieder bei dem, was Sie schon vorher hatten, std::badalloc.

0voto

Ich schließe mich der Meinung an, dass der Ansatz der Vorabzuweisung von 5 MB "verrückt" ist, allerdings aus einem anderen Grund: Er unterliegt Race Conditions. Wenn die Ursache für die Erschöpfung des Speichers in Ihrem Programm liegt (der virtuelle Adressraum ist erschöpft), könnte ein anderer Thread die 5 MB beanspruchen, nachdem Sie sie freigegeben haben, aber bevor Sie sie verwenden können. Wenn die Ursache für die Erschöpfung des Speichers ein Mangel an physischen Ressourcen auf dem Rechner ist, weil andere Prozesse zu viel Speicher verwenden, könnten diese anderen Prozesse die 5 MB beanspruchen, nachdem Sie sie freigegeben haben (wenn die malloc-Implementierung den Speicherplatz an das System zurückgibt).

Einige Anwendungen, wie z. B. ein Musik- oder Filmabspielprogramm, würden bei Zuweisungsfehlern völlig zu Recht einfach beendet/abgestürzt werden - sie verwalten nur wenige oder gar keine veränderbaren Daten. Andererseits bin ich der Meinung, dass jede Anwendung, mit der potenziell wertvolle Daten verändert werden, eine Möglichkeit haben muss, (1) sicherzustellen, dass die bereits auf der Festplatte befindlichen Daten in einem konsistenten, nicht beschädigten Zustand belassen werden, und (2) eine Art Wiederherstellungsjournal zu schreiben, so dass der Benutzer bei nachfolgenden Aufrufen alle Daten wiederherstellen kann, die verloren gingen, als die Anwendung gezwungen wurde, sich zu beenden.

Wie wir im ersten Absatz gesehen haben, funktioniert Ihr Ansatz "5 MB malloc und freigeben" aufgrund von Race Conditions nicht. Idealerweise wäre der Code zur Synchronisierung von Daten und zum Schreiben von Wiederherstellungsinformationen völlig allokationsfrei; wenn Ihr Programm gut konzipiert ist, ist es wahrscheinlich von Natur aus allokationsfrei. Ein möglicher Ansatz, wenn Sie wissen, dass Sie in dieser Phase Zuweisungen benötigen, ist die Implementierung eines eigenen Allokators, der in einem kleinen statischen Puffer/Pool arbeitet, und dessen Verwendung während der Abschaltung bei Zuweisungsfehlern.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X