3

GLib について質問があります。サーバー コンテキストで GLib を使用したいのですが、メモリの管理方法がわかりません: https://developer.gnome.org/glib/stable/glib-Memory-Allocation.html

メモリを割り当てるための呼び出しが失敗した場合、アプリケーションは終了します。これは、呼び出しが成功したかどうかを確認する必要がないことも意味します。

ソース コードを見ると、g_malloc が失敗すると、g_error が呼び出されます。

g_error()

g_error(...) を定義する

エラー メッセージをログに記録する便利な関数/マクロ。エラー メッセージは常に致命的であり、その結果、アプリケーションを終了するために abort() が呼び出されます。[...]

しかし、私の場合、サーバー アプリケーションを開発しているので、アプリケーションを終了させたくありません。従来の malloc 関数のように、GLib 関数は NULL を返すか、エラーが発生したことを示す何かを返します。

それで、私の質問は、メモリ不足を処理する方法はありますか? GLib はサーバー目的のアプリケーションには推奨されませんか?

man of abort を見ると、シグナルを処理できることがわかりますが、メモリ不足エラーの管理が少し面倒になります...

abort() 関数は、シグナル SIGABRT が捕捉されていて、シグナル ハンドラが戻らない場合を除き、プログラムの異常終了を引き起こします。

助けてくれてありがとう!

4

2 に答える 2

3

メモリ不足から回復するのは非常に困難です。その理由は、メモリ不足がなくなる前にしばらくの間持続するという意味で、最終的な状態と見なすことができるからです。メモリ不足に対応する (ユーザーに通知するなど) でも、たとえばメッセージを作成して送信するために、より多くのメモリが必要になる場合があります。関連する問題として、メモリの割り当てに関して過度に楽観的なオペレーティング システム (少なくとも Linux) が存在することがあります。メモリが不足していることをカーネルが認識すると、コードがエラーを処理している場合でも、アプリケーションを強制終了する可能性があります。

したがって、システム全体を平均よりもはるかに厳密に把握しているか、メモリ不足エラーをうまく処理できないかのどちらかであり、この場合、ヘルパー ライブラリが何をしているかは問題ではありません。

glib を使用しながらメモリ割り当てを本当に制御したい場合は、部分的な方法があります。glib 割り当て関数は使用せず、他のライブラリの関数を使用してください。Glib は、必要に応じて「フリー関数」を受け取る関数を提供します。例えば:

https://developer.gnome.org/glib/2.31/glib-Hash-Tables.html#g-hash-table-new-full

ハッシュ テーブル コンストラクターは、キーと値の両方を破棄する関数を受け入れます。あなたの場合、データはカスタム割り当て関数を使用して割り当てられますが、ハッシュデータ構造は glib 関数で割り当てられます。

別の方法として、g_try_* マクロを使用してメモリを割り当てることもできます。これにより、引き続き glib アロケータを使用できますが、エラーで中止されることはありません。繰り返しますが、これは問題を部分的にしか解決しません。内部的には、glib はアボートする可能性のある関数を暗黙的に呼び出し、エラー時に決して返らないと想定します。

一般的な質問について: サーバーがメモリ不足のときにクラッシュするのは理にかなっていますか? 明らかな答えは「いいえ」ですが、この答えがどれほど理論的であるかを見積もることはできません。サーバーシステムがその操作に対して適切なサイズであり、その容量を超える可能性のある入力を無効として拒否することしか期待できません。そのため、どのライブラリを使用するかは問題ではありません。

于 2013-06-07T00:46:28.923 に答える
1

私はおそらくここで少し編集していますが、仮想/論理メモリを使用する現代の傾向 (両方の名前が使用されていますが、「論理」の方がより明確です) は、メモリがいつ使い果たされたかを知ることを劇的に複雑にします。 Linux の古い実際の (RAM + スワップ) モデル (これを物理モデルと呼びます) は、次のようになります/etc/sysctl.d/10-no-overcommit.conf

vm.overcommit_memory = 2
vm.overcommit_ratio = 100

mallocこれにより、プログラムが単に失敗した場合、そのプログラムがメモリ不足の実際の原因である可能性が高く、現在のオブジェクトの構築から離れfreeて途中でメモリを使用できるという哲学を持つ能力が回復します。あまりにも多くの RAM を必要とするクレイジーなものを要求し、次の要求を待っていることに対してユーザーに不平を言う可能性があります。このモデルでは、ほとんどの OOM 条件はほぼ瞬時に解決されます。プログラムは対処しておそらく RAM を返すか、次の SEGV によって返された 0 を使用しようとするとすぐに強制終了されmallocます。

2013年にLinuxがデフォルトで使用する傾向がある仮想/論理メモリモデルでは、これは機能しません。これは、プログラムがメモリを見つけられないためですmalloc. RAMのどこにもないことに気づきます。ホストの RAM を使い果たしたプログラムではなく、システム上のすべてのプログラムが停止する可能性があるため、これは大惨事になります。一部の GLib 関係者がこの問題を修正しようとさえ気にかけない理由は理解できます。なぜなら、論理メモリ モデルでは修正できないからです。

論理メモリの本来の目的は、ホストのメモリの半分以上を使用する巨大なプログラムがサポート プログラムをフォークして実行できるようにすることでした。通常、その特定の使用パターンを持つホストでのみ有効にされていました。2013 年にホーム ワークステーションが 24 GiB 以上の RAM を搭載できるようになった現在、99% の確率で論理メモリを有効にする言い訳はありません。起動時に RAM が 4 GiB を超えるホストでは、おそらくデフォルトで無効にする必要があります。

ともかく。古い学校の物理モデルのアプローチを採用したい場合は、コンピューターでそれが有効になっていることを確認してください。そうしないと、mallocとのrealloc呼び出しをテストしても意味がありません。

あなたそのモデルにいるなら、GLib は実際には同じ哲学に導かれていないことを思い出してください ( http://code.google.com/p/chromium/issues/detail?id=51286#c27を参照してください。それらのうちです)。GLib に基づくすべてのライブラリも同様に感染する可能性があります。ただし、物理メモリ モデルで GLib を使用すると、独自のメモリ ハンドラを で置き換えることによって、興味深いことができるg_mem_set_vtable()可能性があります。これは、プログラム グローバルをいじり、キャッシュなどの使用量を減らしてスペースを解放できる可能性があるためです。 、次に基になる を再試行しmallocます。ただし、特別なハンドラーが呼び出された時点でどのオブジェクトが構築中であったかがわからないため、それ自体が制限されます。

于 2013-07-10T23:20:29.220 に答える