C ++ゲームはメモリ割り当てエラーをどのように処理しますか?


23

私はC ++で書かれているが例外を使用しないいくつかのゲームを知っています。C ++でのメモリ割り当てエラーの処理は一般にstd::bad_alloc例外を中心に構築されているため、これらのゲームはどのようにそのようなエラーを処理しますか?

それらは単にクラッシュしますか、またはメモリ不足エラーを処理して回復する別の方法がありますか?


1
割り当てが成功したと主張する特定の環境/ OSがありますが、メモリを使用しようとすると、(または他の)プログラムがクラッシュすることに注意してください
PlasmaHH

6
ゲーム中に割り当てが失敗すると、Quake 3はエラーメッセージを表示してメニューに戻ります。これは、Quake 3のプールアロケーターによって可能になったと思います。プールアロケーターは、プール全体をドロップし、プールがなくなったら安全にメニューに戻ることができます。
ディートリッヒEpp

16
通常、クラッシュします。
user253751 16

1
例外が本当に無効になっている場合、プログラムは代わりにを呼び出す必要がありstd::terminate、それだけです。ただし、同じ制限の下で、割り当ては例外をスローする代わりにNULLポインターを返すことができ、その結果は個別にチェックおよび処理できます。
underscore_d

2
C ++では、言うことができますClassName variableName = new(nothrow) ClassName();明らかにクラス名、変数名などを置き換えます)。その後、割り当てが失敗した場合、if(!variableName)try-catch例外ブロックなしでエラーを処理できるようにすることでそれを検出できます。メモリは同じ機能を使用して割り当てられている場合も同様に、malloc()calloc()割り当てる次いで、等、障害を同じ用いて検出することができるif(!variableName)のtry-catchを必要とせずに方法を。ゲームがこれらのエラーを処理する方法については、その時点で、クラッシュするかどうかを判断するのはゲーム開発者の責任です。
スペンサーD

回答:


63

すべての平均的なプログラムと同じ:ありません。*

ほとんどのアプリケーションでは、メモリがなくなっても機能し続けるという顧客の期待はありません。すべてのゲームはこれらの「ほとんどのアプリケーション」に該当します。顧客が仕事をすることを期待していないエッジケースに取り組むために時間とお金を費やすことは意味がありません。

質問は次のようになります。

  • ハードディスクがいっぱいの場合、どのようにゲームをインストールしますか?
  • 最小スペック以下のPCで、どのようにして高いfpsでゲームを実行しますか

答えは同じです。これらはユーザーの問題です。ゲームは気にしません。


*実際には、彼らは通常、例外を高レベルでキャッチし、クラッシュ/終了する前にイベントをログに記録しようとするために、ゲームの開始時に事前に割り当てられたメモリを使用します。このログにより、カスタマーサポートは問題に費やす時間を減らすことができます。


2
:メモリ割り当て障害が発生した場合になどロギング用メモリを、事前に割り当てるにはstackoverflow.com/questions/7749066/...
bwDraco

23

通常、この種のシナリオは発生しません。

第一に、最新のオペレーティングシステムの仮想メモリは、とにかく通常の操作で発生する可能性が非常に低いことを意味します。暴走割り当てのバグがない限り、ゲームはOSの仮想アドレス空間からメモリを割り当て、OSはページインとページアウトの後に監視します。

それはすべて順調ですが、コンソールや古いOSには実際には適用されません。そのため、ゲームは、とにかく標準ライブラリアロケーターを使用して多くの小さな動的割り当てさえ行いません。代わりに、起動時に一度だけメモリの大きなプールを割り当て、必要な実行時割り当てのためにそのプールから引き出します(たとえば、C ++配置を使用するか、独自のメモリ管理システムを作成することにより)その上)。

また、ゲームはメモリリークから保護します。これは、ゲームが小さな個々の割り当てを追跡して考慮する必要がなく、プール全体を破棄してメモリを回収できるためです。

そして第三に、ゲームは常に最小仕様を設定し、その範囲内でメモリ使用量を割り当てます。したがって、ゲームが1GBのRAMを必要とするように指定されている場合、そのメモリ使用量が1GBを超えない限り、RAMの不足を心配する必要はありません。


3
「代わりに、起動時に一度だけメモリの大きなプールを割り当て、必要な実行時割り当てのためにそのプールから引き出します」-そして、プールがいっぱいになったらどうなりますか?
user253751 16

@immibis-3つ目のポイントをご覧ください。
マキシマスミニマス

2
@immibisつまり...プールが空の場合はどうしますか?システムメモリとは異なり、プールのサイズと使用量はアプリケーションの制御下にあります。そのため、アプリケーションにバグがない限り、プール空にすることはできません
デビッドシュワルツ

@DavidSchwartzまたは、カーネルがメモリオーバーコミットを使用していない場合。Linuxはこれを行います。zswapまたはzramを介してページファイルの圧縮が有効になっている場合、プールをゼロにしても効果はありません。
ダミアンジェリック16

1
これは実際の質問に答えているようには見えませんが、代わりに「この船は沈められないので、何のために緊急措置が必要でしょうか?」
リリエンタール

2

まあ、主に、例外が存在する前にやったのと同じ方法-古い「戻り値のアプローチをチェックする」。アロケーターが例外を使用しない場合、通常、アロケーターはnull失敗したときに戻ります。よく書かれたゲームはそれをチェックし、安全な方法で状況を処理します。時々、これはゲームを終了することを意味します(例std::terminate)、または少なくとも最後の既知の安全な状態に戻すことを意味します(たとえば、プールから割り当てた場合、プールが安全でない状態でも安全に破棄できます)。

そのような場合でも、多くのゲームは例外を使用します。誰かが「ゲームコードでの例外の使用を避ける」と言うとき、彼らが通常意味するのは「通常のフロー制御ではなく、真に例外的な場合にのみ例外を使用する」ということです。メモリー不足の例外をキャッチするためのセットアップは安価です。コストはほとんど例外なく、例外の処理に伴う複雑さです。典型的なメモリ不足の場合、これらのどちらも非常に重要ではありません-ほとんどの場合、とにかく終了する必要があります。

気を付けてください、ほとんどのゲームはただクラッシュします。これは見た目ほどクレイジーではありません-通常、ターゲットとしてある程度のメモリ使用量があり、ゲームがその制限に達していないことを確認します(たとえば、RTSゲームでユニットカウント制限を使用するか、 FPSのセクション内の敵の量)。そうしなくても、通常、合理的な最新システムではメモリ不足になりません。たとえば、仮想アドレス空間(32ビットアプリケーション)またはスタックが不足します。OSは、要求されただけのメモリを持っていることを既に装います。これは、仮想メモリが提供する抽象化の1つです。ポイントは、256 MiBの物理RAMがあるからといって、アプリケーションが4 GiBのメモリを使用できないということではありません。一部のゲームは、すべてのデータがそうではないことをあまり気にしないかもしれません」


1

例外キャッチすることと、例外がいつ発生したか決定することは、2つの異なることです。

プログラムが必要としないメモリを解放するには、複雑なロジックが必要です。さらに悪いことに、他の実行中のプログラムまたはライブラリがメモリをリークしている場合、あなたはそれを制御できません

正常にシャットダウンするためにできるのは良いことだけで、それがほとんどのプログラムが行うことを選択することです。プログラムが応答しなくなるため、メモリが使用可能になるまで待つことさえできません。


OPが言ったように、問題のゲームが文字通り「例外を使用しない」場合、それらはキャッチ、レイズ、または処理できません。例外が無効になっていて、誰かが例外をスローした場合、プログラムは代わりにを呼び出す必要がありstd::terminate、それだけです。しかし、そのような状況では、割り当ては例外をスローする代わりにヌルポインターを返すことができ、それは個別に処理できます。
underscore_d
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.