Mir sind einige Spiele bekannt, die in C ++ geschrieben sind, aber keine Ausnahmen verwenden. std::bad_alloc
Wie gehen diese Spiele mit einem solchen Fehler um, da die Behandlung von Speicherzuweisungsfehlern in C ++ im Allgemeinen um die Ausnahme herum aufgebaut ist ?
Stürzen sie einfach ab, oder gibt es eine andere Möglichkeit, mit einem Fehler aufgrund von Speichermangel umzugehen und ihn zu beheben?
c++
resource-management
memory
user200783
quelle
quelle
std::terminate
, und das war's. Unter derselben Einschränkung kann die Zuweisung jedoch einen Nullzeiger zurückgeben, anstatt eine Ausnahme auszulösen, und dieses Ergebnis kann separat überprüft und behandelt werden.ClassName variableName = new(nothrow) ClassName();
( Klassennamen, Variablennamen usw. offensichtlich ersetzen ). Wenn die Zuordnung fehlschlägt, können Sie dies erkennen, indem Sie sagen,if(!variableName)
dass der Fehler ohne einen Try-Catch-Ausnahmeblock behandelt werden kann. Ebenso, wenn der Speicher eine Funktion wie zugeteilt verwendetmalloc()
,calloc()
usw., dann können Ausfälle zuzuteilen detektierenden Verwendung derselbenif(!variableName)
Methode ohne eine try-catch zu benötigen. Was den Umgang der Spiele mit diesen Fehlern angeht, ist es nun an den Spielentwicklern zu entscheiden, ob sie abstürzen oder nicht.Antworten:
Wie bei allen durchschnittlichen Programmen: Sie tun es nicht. *
Für die meisten Anwendungen besteht keine Kundenerwartung, dass sie weiterarbeiten, sobald der Speicher voll ist. Alle Spiele fallen unter diese "meisten Anwendungen". Es macht keinen Sinn, Zeit und Geld für die Bearbeitung eines Edge-Falls zu investieren, von dem der Kunde nicht erwartet, dass er funktioniert.
Die Frage ähnelt der folgenden:
Die Antwort ist die gleiche: Dies sind die Probleme der Benutzer. Das Spiel ist mir egal.
* Tatsächlich führen sie normalerweise einen High-Level-Catch der Ausnahme durch und verwenden zu Beginn des Spiels vorab zugewiesenen Speicher, um zu versuchen, das Ereignis vor dem Absturz / Beenden zu protokollieren. Das Protokoll ermöglicht dem Kundensupport, weniger Zeit für das Problem zu verschwenden.
quelle
Typischerweise passiert so ein Szenario nie.
Erstens bedeutet virtueller Speicher auf modernen Betriebssystemen, dass es im normalen Betrieb sowieso sehr unwahrscheinlich ist. es sei denn, Sie haben einen außer Kontrolle geratenen Zuweisungsfehler, das Spiel weist Speicher aus dem virtuellen Adressraum des Betriebssystems zu und das Betriebssystem kümmert sich um das Ein- und Auslagern.
Das ist alles in Ordnung und gut, aber nicht wirklich für Konsolen oder ältere Betriebssysteme. Zweitens führen Spiele mit Standardbibliothekszuweisern ohnehin nicht einmal viele kleine dynamische Zuweisungen durch. Stattdessen reservieren sie einen großen Speicherpool einmalig beim Start und greifen auf alle erforderlichen Laufzeitzuordnungen zurück (z. B. durch Verwendung von C ++, das neu platziert wird, oder durch Schreiben eines eigenen Speicherverwaltungssystems darauf) oben drauf).
Dies schützt auch vor Speicherverlusten, da ein Spiel nicht nur die einzelnen Zuordnungen nachverfolgen und abrechnen muss, sondern auch den gesamten Pool wegwirft, um Speicherplatz freizugeben.
Und drittens legen Spiele immer eine Mindestspezifikation fest und budgetieren ihren Speicherverbrauch darin. Wenn für ein Spiel 1 GB RAM erforderlich ist, bedeutet dies, dass es sich niemals Sorgen machen muss, dass der Arbeitsspeicher knapp wird, solange die Speichernutzung 1 GB nicht überschreitet.
quelle
Nun, hauptsächlich so, wie wir es gemacht haben, bevor es Ausnahmen gab - den alten "Check the Return Value Approach". Wenn ein Allokator keine Ausnahmen verwendet, wird er normalerweise zurückgegeben,
null
wenn eine Allokation fehlschlägt. Ein gut geschriebenes Spiel prüft dies und geht sicher mit der Situation um. Manchmal bedeutet dies, das Spiel zu beenden (z. B.std::terminate
) oder zumindest zum letzten bekannten sicheren Zustand zurückzukehren (z. B. können Sie den gesamten Pool sicher entsorgen, auch wenn er sich in einem unsicheren Zustand befindet).Viele Spiele verwenden auch dann noch Ausnahmen für solche Fälle. Wenn jemand sagt "Vermeiden Sie die Verwendung von Ausnahmen im Spielcode", bedeutet dies normalerweise "Verwenden Sie Ausnahmen nur für wirklich außergewöhnliche Fälle, nicht für die weltliche Ablaufsteuerung". Das Setup für das Abfangen einer Ausnahmebedingung aufgrund unzureichenden Arbeitsspeichers ist günstig - die Kosten sind hauptsächlich im Wurf und die Komplikationen bei der Behandlung der Ausnahmebedingung. Beides ist in einem typischen Fall von Speichermangel nicht sehr wichtig - Sie möchten sowieso fast immer kündigen.
Wohlgemerkt, die meisten Spiele werden einfach abstürzen. Dies ist nicht so verrückt, wie es sich anhört - Sie haben normalerweise eine gewisse Speichernutzung als Ziel und stellen sicher, dass Ihr Spiel diese Grenze nicht erreicht (z. B. indem Sie in einem RTS-Spiel eine Begrenzung für die Einheitenzahl verwenden oder die Begrenzung der Anzahl der Feinde in einem Abschnitt eines FPS). Selbst wenn dies nicht der Fall ist, wird auf einem einigermaßen modernen System in der Regel nicht genügend Arbeitsspeicher zur Verfügung stehen - beispielsweise nicht genügend virtueller Adressraum (in einer 32-Bit-Anwendung) oder nicht genügend Stapelspeicher. Das Betriebssystem gibt bereits vor, dass Sie über so viel Speicher verfügen, wie Sie benötigen - dies ist eine der Abstraktionen, die der virtuelle Speicher bietet. Nur weil Sie über 256 MB physischen Arbeitsspeicher verfügen, bedeutet dies nicht, dass Ihre Anwendung nicht 4 GB Arbeitsspeicher verwenden kann. Einige Spiele stören sich vielleicht gar nicht daran, dass all ihre Daten nicht vorhanden sind.
quelle
Das Abfangen einer Ausnahme und die Entscheidung, was zu tun ist, wenn eine Ausnahme ausgelöst wird, sind zwei verschiedene Dinge.
Sie benötigen eine komplexe Logik, um Speicher freizugeben, der von Ihrem Programm nicht benötigt wird. Schlimmer noch, wenn ein anderes laufendes Programm oder eine andere Bibliothek den Speicher verliert, haben Sie keine Kontrolle darüber
Es ist nur gut, dass Sie es schaffen, ordnungsgemäß herunterzufahren, und genau das werden die meisten Programme tun. Sie können nicht einmal warten, bis Speicher verfügbar ist, da Ihr Programm sonst nicht mehr reagiert.
quelle
std::terminate
, und das wars. Unter solchen Bedingungen kann die Zuweisung jedoch einen Nullzeiger zurückgeben, anstatt eine Ausnahme auszulösen, und dies kann separat behandelt werden.