int *p;
while(true)
{
p = new int;
}
メモリスペースが不足しているため、このコードがクラッシュしないようにする必要があります。pの値、つまりpに配置されているメモリのアドレスを出力してみましたが、増加しているように見えますが、クラッシュは発生していません。
なんでそうなの?
int *p;
while(true)
{
p = new int;
}
メモリスペースが不足しているため、このコードがクラッシュしないようにする必要があります。pの値、つまりpに配置されているメモリのアドレスを出力してみましたが、増加しているように見えますが、クラッシュは発生していません。
なんでそうなの?
この解決策は、1MPHを運転しているときに、通りの電柱で車をクラッシュさせようとするようなものです。最終的には発生しますが、高速な結果が必要な場合は、速度を少し上げる必要があります。
int *p;
while (true) {
p = new int[1024*1024*1024];
}
しかし、私の答えは、失敗したメモリ割り当てをスローする標準のSTLアロケータを使用するコードベースに基づいています。NULL
失敗した割り当てに単に戻る他の利用可能なアロケータがあります。失敗した割り当ては致命的とは見なされないため、このタイプのアロケータがこのコードでクラッシュすることはありません。NULL
エラーを検出するには、の割り当ての戻りを確認する必要があります。
もう1つの注意点は、64ビットシステムで実行している場合、アドレススペースのサイズが大きくなるため、クラッシュするのにかなり長い時間がかかる可能性があることです。電話の世論調査が通りを下っている代わりに、それは全国にあります。
クラッシュが表示されるまで、この質問を閉じないようです:)
Unixライクなオペレーティングシステムでは、 ulimitコマンドを使用して、プロセスで使用できる仮想メモリの量を制限できます。VMを1MBに設定することで、約5秒で目的の結果を確認できました。
$ ulimit -v $((1024*1024)) # set max VM available to process to 1 MB
$ ulimit -v # check it.
1048576
$ time ./a.out # time your executable.
terminate called after throwing an instance of 'St9bad_alloc'
what(): std::bad_alloc
Aborted
real 0m5.502s
user 0m4.240s
sys 0m1.108s
メモリの小さなチャンクのいくつかの割り当ては、1つの大きな割り当てよりも遅くなります。たとえば、100万バイトを4回割り当てるよりも、4バイトを100万回割り当てる方が時間がかかります。
一度に大きなメモリチャンクを割り当ててみてください。
int *p;
while(true)
{
p = new int[1024*1024];
}
あなたは十分長く待たなかった。
[進行状況を確認したい場合は、1000000ループごとに出力を追加するなどしてください。最終的には失敗します。]
別の可能性:ほとんどのOSは楽観的な割り当てを実行します。たとえば500MBをmallocすると、プログラムが実際にメモリの読み取りまたは書き込みを試みるまで、そのメモリは実際には予約されない場合があります。
特にLinuxは、メモリを過剰に約束し、カーネルの約束を収集しようとするプロセスを攻撃するためにOOM(メモリ不足)キラーに依存していることで有名です。
コンパイラは最適化を行っており、実際にはメモリを割り当てていないと思います。上記の例を(valgrindを使用して)何度か実行したところ、割り当てがあり、すべてが0バイトのメモリであることがわかりました。
これを試してみると、プログラムが強制終了されます(少なくともUNIXでは):
#include <cstdio>
int main() {
int *p;
while (true) {
p = new int[1024*1024];
p[0] = 0;
printf("%p\n",p);
for(unsigned j = 1; j < 1024*1024; j++) {
p[j] = p[j-1] + 1;
}
}
return 0;
}
唯一の違いは、割り当てられたメモリを使用することです。
つまり、OSがプロセスを強制終了するだけでプロセスのクラッシュを防いでいると思うので、実際にはクラッシュしません(これについては100%確実ではありません)