2009-10-31 1 views
21

私はLinux上でのメモリ条件のうち、約読んでいると、manページから次の段落は私が考えていました:デフォルトではLinuxの楽観的なmalloc:メモリ不足時にnewが常にスローされますか?

、Linuxは楽観的メモリ配置戦略を用いています。つまり、malloc()がNULL以外の値を返すと、メモリが実際に利用可能であるという保証はありません。これは本当に悪いバグです。システムのメモリが不足していると判明した場合、悪名高いOOMキラーによって1つ以上のプロセスが強制終了されます。 [...]

オペレータの新しい実装がある時点でmallocを呼び出してしまうことを考えれば、実際にLinuxで新しいことが保証されるのでしょうか?存在しない場合、どうやらこれは明らかに検出不能なエラー状況を処理しますか?

+0

今すぐご覧ください。しないでください。あなたが何を投げているのか、誰がポインターを受けているのか、また誰がOOMを殺したのか、なぜそれをコントロールすることはできないのですか?それはあなた次第ではありません。それはただのLinuxです。 –

+1

@ジョナサン・レフラー:タイトルを「いつも」に変更しました。新しいものが正常に返されても、使用可能なメモリがない場合は、C++標準に準拠していません。そういう意味では、本当に「新しいことはいつもスローされますか?または、「新しいことは投げられないだろうか? 「新しいことは今までに投げつけませんか?」 (私はどんなつま先を踏みたいとは思わないが...誰かが私が間違っていると思うかどうかを知らせる...) –

+0

答えてくれてありがとう! – rpg

答えて

17

you can configure the kernel's overcommit settings vm.overcommit_memoryを使用しています。

ハーブサッターは、数年前にどのようにthis behavior is actually nonconforming to the C++ standard議論:でも、要求されたメモリ本当に、どのように割り当てが常に成功することができます

「は、具体的にLinuxでは、メモリ割り当て常に成功し完全停止を含むいくつかのオペレーティングシステム、オン。その理由は、アロケーション自体が単にメモリ要求を記録するだけであり、実際のバッキングストアでは、実際にメモリが要求されるまで(物理または仮想)メモリは実際に要求プロセスにコミットされないからです

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

+13

'buf [100] = 'c''は失敗したり例外をスローしません。その時間が過ぎるとアプリケーションがシステムによって強制終了されるかもしれませんが、アプリケーションはシステムによって*いつでも殺されるかもしれません。 – caf

4

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

たとえば、標準のx86 Linuxでmallocから3GBのメモリを要求すると、ユーザー空間のアプリケーションに与えられるメモリの量を考えると、これは不可能なので、必ずNULLを返します。

+0

それは私が思ったものですが、私はsomoneが1TBのメモリを割り当てて、残念ながらそれが成功したいくつかのオンラインレポートを見てきました。 – rpg

+1

私は64ビットマシンであるとはっきり言っています。たとえ彼がそれほど多くのmemを利用できる方法がないとしても、プロセスのアドレス空間は1TBよりも大きい。 –

9

純粋でシンプルなソフトウェアでは処理できません。

アプリケーションには、完全に有効なポインタが表示されます。いったんアクセスしようとすると、カーネルにページフォルトが生成され、カーネルは物理ページを割り当てようとします。

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

1

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

+0

これをバックアップできますか? PAEであっても32ビットで簡単にできます。 –

+0

@Jed - より根気よく推論を探していますか、これを実証する例が必要ですか?後者の場合は、operator newを無限ループで呼び出してください。 gcc 3.4.5とgcc 4.4.0の両方からのlibstdC++で1メガバッファを割り当てると、3,055回の呼び出しの後にbad_alloc例外がスローされました。 –

2

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

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

+1

少なくとも、すべてのページに触れる必要があります。最初のページと最後のページだけでは十分ではありません。ページ単位で割り当てます(ほとんどの場合、少なくともほとんどのマシンで)。 –

+0

スティーブンは正しいです、すべてのページをタッチする必要があります。しかし、このアプローチの問題点は、このプロセス中にバッキングストアのコミットメントが失敗した場合、アプリケーションがセグメンテーションフォールトでクラッシュするため、何もできないということです。なぜなら、実際に所有しています。セグメンテーションフォルトから回復することはできません(時には 'sigsegv'シグナルを扱うことができますが、それを処理した後も実行を継続することはできません)。 –

+1

セグメンテーション違反で失敗しません。 OOMのkillerのターゲットは 'SIGKILL'で死ぬ。スーパーユーザーが手動で殺すのとは違っていると考えるべきではない。 – caf

関連する問題