26

Linux でのメモリ不足の状態について読んでいて、man ページの次の段落で考えさせられました。

デフォルトでは、Linux は楽観的なメモリ割り当て戦略に従います。これは、malloc() が非 NULL を返す場合、メモリが実際に使用可能であるという保証がないことを意味します。これは本当に悪いバグです。システムのメモリが不足していることが判明した場合、悪名高い OOM キラーによって 1 つまたは複数のプロセスが強制終了されます。[...]

オペレーターの new 実装がある時点で malloc を呼び出すことになることを考えると、Linux で new が実際にスローされるという保証はありますか? そうでない場合、この明らかに検出できないエラー状況をどのように処理しますか?

4

5 に答える 5

21

場合によります; vm.overcommit_memory を使用して、カーネルのオーバーコミット設定を構成できます。

Herb Sutter は、数年前に、この動作が実際に C++ 標準に準拠していないことについて議論しました。

「特にLinuxを含む一部のオペレーティングシステムでは、メモリ割り当ては常に成功します。完全に停止します。要求されたメモリが実際に利用できない場合でも、どのようにして割り当てが常に成功するのでしょうか?その理由は、割り当て自体がメモリの要求を記録するだけだからです。内部では、(物理または仮想) メモリは、メモリが実際に使用されるまで、実際のバッキング ストアを使用して、実際には要求プロセスにコミットされません。

「 new がオペレーティング システムの機能を直接使用する場合、 new は常に成功しますが、 buf[100] = 'c'; のようなその後の無害なコードは、スロー、失敗、または停止する可能性があることに注意してください。標準 C++ の観点からは、両方の効果があります。 C++ 標準では、 new が十分なメモリをコミットできない場合は失敗する必要があり (これはそうではありません)、 buf[100] = 'c' のようなコードは例外をスローしたり、失敗したりすべきではありません (これはそうではありません)。そうかもしれない)。"

于 2009-10-31T21:18:53.157 に答える
9

純粋で単純なソフトウェアで処理することはできません。

アプリケーションでは、完全に有効なポインターを受け取ります。アクセスしようとすると、カーネルでページ フォールトが生成され、カーネルはそれに物理ページを割り当てようとし、割り当てられない場合は ... ブームになります。

しかし、ご覧のとおり、これはすべてカーネル内で行われるため、アプリケーションはそれを見ることができません。重要なシステムの場合は、システムでオーバーコミットをすべて無効にすることができます。

于 2009-10-31T21:23:22.700 に答える
4

malloc はまだ NULL を返すことができると思います。その理由は、使用可能なシステム メモリ (RAM + スワップ) とプロセスのアドレス空間の量に違いがあるためです。

たとえば、標準の x86 Linux で malloc から 3GB のメモリを要求した場合、ユーザー空間アプリに与えられたメモリの量を考えると、これは不可能であるため、確実に NULL が返されます。

于 2009-10-31T21:20:08.130 に答える
3

私が間違っていたらすみませんが、割り当てられたメモリをゼロにしようとするだけで、要求したすべてのバイトがあることを保証するのに十分ではありませんか? または、最後のバイトに書き込むだけでも、メモリが本当にあなたのものではない場合、例外がスローされますか?

そうであれば、メモリの最後の (そして最初の?) バイトに書き込みを試みて、正常に動作するかどうかを確認できます。正常に動作しない場合は、malloc から null を返すことができます。

于 2009-10-31T22:12:41.717 に答える
1

はい、new が最終的にスローする保証が 1 つあります。オーバーコミットに関係なく、アドレス空間の量は制限されています。したがって、メモリを割り当て続けると、遅かれ早かれアドレス空間が不足し、 new が強制的にスローされます。

于 2009-10-31T21:40:54.053 に答える