“メモリ不足”を処理する正しい方法は何ですか?

StackOverflow https://stackoverflow.com/questions/1439977

  •  10-07-2019
  •  | 
  •  

質問

最近、WindowsでCCTVプログラム用のビデオプレーヤープログラムに取り組んでいます。プログラムは同時に多くのビデオストリームをデコードして再生する必要があるため、mallocが失敗し、すべてのmallocの後にチェックを追加するという状況に遭遇する可能性があると思います。

しかし、一般的に言って、私がオープンソースプロジェクトで読んだオープンソースプログラムのこれらのコードでは、mallocの結果のチェックはほとんど見当たりません。そのため、mallocが失敗すると、ほとんどのプログラムがクラッシュします。それは受け入れられないのではないですか?

Linuxでサーバープログラムを作成する同僚は、100のクライアント接続に十分なメモリを割り当てます。そのため、彼のプログラムは101クライアントを拒否する可能性がありますが、mallocの失敗には決して遭遇しません。彼のアプローチはデスクトップアプリケーションにも適していますか?

役に立ちましたか?

解決

Linuxでは、 malloc()が失敗することはありません。代わりに、OOMキラーがトリガーされ、システムが倒れるまでランダムプロセスの強制終了を開始します。 Linuxは現在最も一般的に使用されているUNIXの派生物であるため、多くの開発者は malloc()の結果を決してチェックしないことを学びました。それがおそらく同僚が malloc()の失敗を無視する理由です。

障害をサポートするOSで、2つの一般的なパターンを見ました:

  • malloc()の結果を確認し、割り当てが失敗した場合に abort()を呼び出すカスタムプロシージャを作成します。たとえば、 GLibおよびGTK + ライブラリはこのアプローチを使用します。

  • " purge-able"のグローバルリストを保存します。割り当てに失敗した場合にクリアできるキャッシュなどの割り当て。次に、割り当てを再試行し、それでも失敗する場合は、標準のエラー報告メカニズム(動的割り当てを実行しない)で報告します。

他のヒント

標準化されたAPIに従う

Linuxでも、ulimitを使用して、mallocエラーを迅速に返すことができます。デフォルトで無制限に設定されているだけです。

公開された標準に準拠することへの明確なプレッシャーがあります。ほとんどのシステムでは、長期的には、最終的にはLinuxでも、 malloc(3) は失敗の正しい指示を返します。デスクトップシステムには仮想メモリがあり、ページングを要求しますが、それでも malloc( 3) は、メモリリークのないデバッグされたプログラムでのみ機能します。何かがうまくいかない場合は、誰かが ulimit を設定したいと思うでしょう。追跡します。突然、 malloc チェックが意味をなします。

nullをチェックせずにmallocの結果を使用することは、mallocが失敗する可能性のあるプラットフォームで使用する可能性のあるコードで受け入れられません。これらのコードでは、クラッシュや予測不可能な動作が発生する傾向があります。私は将来を予測することはできません、私のコードがどこに行くのか分からないので、nullを返すmallocのチェックでコードを書くでしょう-予期せずに振る舞うよりも死ぬ方が良い!

mallocが失敗した場合の対処方法は、アプリケーションの種類と、使用しているライブラリに対する信頼度によって異なります。状況によっては、唯一安全なことはプログラム全体を停止することです。

既知のメモリクォータを事前に割り当て、いくつかのチャンクに分割するという考え方は、アプリケーションのメモリ使用量が予測できない場合、実際にメモリを使い果たすことを避けることは良い方法です。これを拡張して、コードで使用する独自のメモリ管理ルーチンを作成できます。

作業中のアプリケーションのタイプによって異なります。個々のタスクが失敗することを許可できる個別のタスクに分割されたアプリケーションが動作する場合、メモリ割り当てのチェックは正常に回復できます。

しかし、多くの場合、mallocの失敗に対応する唯一の合理的な方法は、プログラムを終了することです。避けられないヌル逆参照でコードをクラッシュさせるだけで、それが実現します。間違いなく、エラーを説明するログエントリまたはエラーメッセージをダンプする方が確実に優れていますが、現実の世界では限られたスケジュールで作業しています。時には、ペダンティックなエラー処理の投資収益率が得られないことがあります。

ユーザーにデータを保存してアプリケーションをシャットダウンするように警告できるように、この場合は解放できるバッファーを常にチェックして事前に割り当てます。

作成するアプリによって異なります。もちろん、malloc()の戻り値を常に確認する必要があります。ただし、OOMを適切に処理することは、低レベルの重要なシステムサービスや、それらに使用される可能性のあるライブラリを作成する場合など、まさにそのような場合にのみ意味があります。したがって、OOMで異常終了するmallocラッパーは、多くのアプリやフレームワークで非常に一般的です。多くの場合、これらのラッパーにはxmalloc()などの名前が付けられています。

GLibのg_malloc()も中止されます。

膨大な量のメモリを処理する予定で、「今はメモリ領域ABCがあり、Bピースは必要ないので、必要に応じて行う」などのようにLinuxにステートメントを作成したい場合は、在庫GNU Cライブラリで利用可能なmmap()/ madvise()ファミリーの関数。使用パターンに応じて、コードはmallocを使用するよりも簡単になります。このAPIは、1回だけ読み取り/書き込みを行うファイルをキャッシュすることで、Linuxがメモリを浪費しないようにするためにも使用できます。

これらは、GNU libc情報ドキュメントにうまく文書化されています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top