std::bad_alloc ignorieren oder immer berücksichtigen?
-
Was soll man denn bitte machen, wenn man ein std::bad_alloc erhält?
Die einzige Möglichkeit, die ich sehe, ist Bufferspeicher freigeben, Fehlermeldung ausgeben, exit()/abort().
Genau diese Aktion macht mein new handler; bad alloc wird also gar nicht mehr geworfen.
-
cooky451 schrieb:
In durchschnittlichen Desktop-Apps? Sehe ich genau so. Aber auf einem Server oder einem Datenbankprozess oder Ähnlichem will man lieber nicht gegen die Wand fahren, nur weil eine Allokation fehl schlägt.
Stimmt zwar, aber das verschiebt man auf OS-Level und gibt der Anwendung das Gefühl, unendlich viel Speicher zu haben.
-
Nathan schrieb:
Was soll man denn bitte machen, wenn man ein std::bad_alloc erhält?
Die einzige Möglichkeit, die ich sehe, ist Bufferspeicher freigeben, Fehlermeldung ausgeben, exit()/abort().
Genau diese Aktion macht mein new handler; bad alloc wird also gar nicht mehr geworfen.Aufräumen, Temp-Dateien löschen, sich von Netzwerkpartnern höflich verabschieden, Datenbankverbindung kappen, ...
Also bad_alloc nicht fangen und regieren, sondern ruhig bis zur main() hochrauschen lassen.
-
bad_allprog schrieb:
Stimmt zwar, aber das verschiebt man auf OS-Level und gibt der Anwendung das Gefühl, unendlich viel Speicher zu haben.
Und wenn die Platte auch voll ist, was dann? Das ist jetzt auch nicht undenkbar. Zudem dürfte eine Festplatte in einige Fällen auch so langsam sein, dass ein geordneter Rückzug am Ende wünschenswerter ist. Ich fürchte, es wird einfach immer ein paar Programme geben die dieses Problem nicht einfach ignorieren können.
Nathan schrieb:
Was soll man denn bitte machen, wenn man ein std::bad_alloc erhält?
Paradebeispiel wäre z.B. das Leeren von Caches. Oder das Warten auf i/o; wenn man z.B. wartet bis das (asynchrone) Schreiben in eine Datei abgeschlossen ist, wird danach der Speicher in dem die zu schreibenden Daten standen frei gegeben. Je nach Anwendung gibt es durchaus einige Möglichkeiten, wobei das Programm danach sogar normal weiter laufen kann.
-
cooky451 schrieb:
bad_allprog schrieb:
Stimmt zwar, aber das verschiebt man auf OS-Level und gibt der Anwendung das Gefühl, unendlich viel Speicher zu haben.
Und wenn die Platte auch voll ist, was dann?
Soweit darf es gar nicht erst kommen. Das Programm checkt natürlich immer mal wieder den Speicherverbrauch und unternimmt entsprechend Aktionen, den Cache verkleinern, die Anzahl Worker reduzieren, etc (z.B. alle 1sec oder im eigenen malloc). Und wenn alles nicht hilft, dann wird ein geordneter Neustart unternommen.
Sind aber alles Sachen, die du nicht machen kannst, wenn du etwas allokierst. Das muss irgendwo zentral geschehen und da ist bad_alloc hinderlich.
Also entweder bad_alloc bis auf main durchrauschen lassen oder ein kluges Memory-System ohne bad_alloc.
-
bad_allprog schrieb:
Soweit darf es gar nicht erst kommen. Das Programm checkt natürlich immer mal wieder den Speicherverbrauch und unternimmt entsprechend Aktionen, den Cache verkleinern, die Anzahl Worker reduzieren, etc (z.B. alle 1sec oder im eigenen malloc).
Sind aber alles Sachen, die du nicht machen kannst, wenn du etwas allokierst. Das muss irgendwo zentral geschehen und da ist bad_alloc hinderlich.
Momentchen! Dein new kann durchaus schlau sein und die Sachen alle machen. Und Dein new_handler kann durchaus Caches leeren, Worker reduzieren und ein Sekundchen warten, damit Threads auslaufen, Threads abschießen, und alles versuchen. Wenns nicht klappt, noch ein Fitzelchen Speicher zu bekommen, dann passiert halt bad_alloc. Das passt doch herrlich zusammen.
Also entweder bad_alloc bis auf main durchrauschen lassen oder ein kluges Memory-System ohne bad_alloc.
Freiwilliger Verzicht auf RAII passt mir nicht in den Kram.
Und wenn alles nicht hilft, dann wird ein geordneter Neustart unternommen.
Jo, typischerweise in der Endlosschleife in der main(), oder? Die main() muss alles fangen, so oder so.
-
der einzige Punkt wo ich bad_alloc krige ist, wenn ich Speicher anforder der größer ist als die verbliebenen physischen Resourcen+alle vom Betriebssystem überwachten Buffer. Wenn das schief geht ist s normalerweise wurscht, kleine Allokationen werden dort meistens noch gehen.
Bei kleinen Allokationen würde ich niemals bad_alloc erwarten - an dem punkt swapt sich das System mit hoher Wahrscheinlichkeit eh gerade tot und geordnetes Abbauen ist aufgrund des überforderten Schdulers nicht mehr möglich.
Daher erwarte ich niemals bad_alloc
-
Nein physischer Speicher ist nicht der Punkt, wie ich vor einigen Wochen feststellen musste (die älteren mögen sich vllt erinnern).
Windows schiebt bei 2GB pro process einen Riegel vor und dann kommt schon bad_alloc...
-
Windows schiebt bei 2GB pro process einen Riegel vor und dann kommt schon bad_alloc...
Nur bei 32-Bit-Anwendungen.
-
Auf 32 Bit Systemen mag es Sinn machen sich den Kopf darüber zu zerbrechen. Oder auf nicht-Desktop Systemen. Dummerweise ist es alles andere als einfach, und die meisten Leute die versuchen den Fall zu behandeln machen es falsch.
Auf 64 Bit Systemen sehe ich kein echtes Problem wenn man den Fall ignoriert. Wenn da ein
bad_allocfliegt ist das typischerweise zu einem Zeitpunkt wo man sowieso schon lange nicht mehr mit dem System arbeiten mag. Ausgenommen man deaktiviert das Pagefile natürlich, dann läuft alles noch halbwegs gut bis zu dem Zeitpunkt wo der Speicher alle ist.Und wenn es dazu kommt, dann bei 64 Bit nicht weil der Adressraum alle ist (wie bei 32 Bit), sondern weil das OS wirklich keinen Speicher mehr besorgen kann.
Wodurch sich die Frage ergibt ob man dann überhaupt nenbad_allocbekommt, oder ob das OS nicht gleich den Prozess killt. Gibt nämlich Fälle wo das OS gleich den Prozess abschiessen wird. Bzw. den entsprechenden Handler der CRT aufrufen, der dann aber auch nix machen kann als den Prozess zu terminieren.Und selbst wenn man den
bad_allocbekommt, ist nicht sichergestellt dass das Programm weiterlaufen kann. Einen solchen Fall hab ich eh bereits in einem anderen Thread beschrieben.EDIT: Link korrigiert.