9

学生時代の自問自答だったのですが、納得のいく答えが得られず、少しずつ頭から離れていきました…今日に至ります。

返されたポインターが NULL かどうかをチェックするか、bad_alloc 例外を処理することで、割り当てメモリ エラーに対処できることがわかりました。

わかりましたが、疑問に思います: newの呼び出しが失敗する可能性があるのはなぜですか? 私の知る限り、空きストアに十分なスペースがない場合、割り当てメモリが失敗する可能性があります。しかし、このような状況は、数 GB の RAM (少なくとも通常のコンピューターでは。組み込みシステムについて話しているわけではありません) を使用して、今日実際に発生しますか? アロケーション メモリ エラーが発生する可能性がある他の状況はありますか?

4

4 に答える 4

6

明らかな「メモリ不足」とは別に、メモリの断片化もこれを引き起こす可能性があります。次のことを行うプログラムを想像してください。

  • メインメモリがほぼいっぱいになるまで:
    • 1020 バイトを割り当てる
    • 4 バイトを割り当てる
  • 1020 バイト ブロックをすべて解放する

メモリ マネージャーがこれらすべてを割り当てられた順序でメモリに順番に配置すると、十分な空きメモリができますが、1020 バイトを超える割り当てでは、それらを配置するための連続したスペースを見つけることができず、失敗します。

于 2013-09-08T14:43:26.103 に答える
5

通常、最新のマシンでは、仮想アドレス空間が不足しているため失敗します。2/3 GB を超えるメモリ1を割り当てようとする 32 ビット プロセスがある場合、割り当てを満たす物理 RAM (またはページング ファイル) があっても、単に仮想アドレス空間にスペースがありません。そのような新しく割り当てられたメモリをマップします。

別の (同様の) 状況は、仮想アドレス空間が大幅に断片化されている場合に発生し、連続したアドレスが十分にないために割り当てが失敗します。

また、メモリ不足発生する可能性があり、実際に先週そのような状況に陥りました。ただし、この場合、いくつかのオペレーティング システム (特に Linux) は NULL を返しません。Linux は、まだコミットされていないメモリ領域へのポインターを喜んで提供し、プログラムが書き込みを試みるときに実際にそれを割り当てます。その時点で十分なメモリがない場合、カーネルはメモリを大量に消費するプロセスを強制終了してメモリを解放しようとします (この動作の例外は、RAM とスワップ パーティションの全容量を超えて割り当てようとした場合のようです)。 - そのような場合は、NULL前払いを取得します)。

malloc から NULL を取得するもう 1 つの原因は、プロセスに対して OS によって適用される制限が原因である可能性があります。たとえば、このコードを実行しようとすると

#include <cstdlib>
#include <iostream>
#include <limits>

void mallocbsearch(std::size_t lower, std::size_t upper)
{
    std::cout<<"["<<lower<<", "<<upper<<"]\n";
    if(upper-lower<=1)
    {
        std::cout<<"Found! "<<lower<<"\n";
        return;
    }
    std::size_t mid=lower+(upper-lower)/2;
    void *ptr=std::malloc(mid);
    if(ptr)
    {
        free(ptr);
        mallocbsearch(mid, upper);
    }
    else
        mallocbsearch(lower, mid);
}

int main()
{
    mallocbsearch(0, std::numeric_limits<std::size_t>::max());
    return 0;
}

Ideoneでは、最大割り当てサイズが約 530 MB であることがわかります。これはおそらくsetrlimit(Windows にも同様のメカニズムが存在します) によって強制される制限です。


  1. OS によって異なり、多くの場合、構成できます。32 ビット プロセスの仮想アドレス空間の合計は 4 GB ですが、現在の主流のすべての OS では、その大部分 (デフォルト設定の 32 ビット Windows では上位 2 GB) がカーネル データ用に予約されています。
于 2013-09-08T14:43:19.603 に答える
1

特定のプロセスで使用できるメモリの量は有限です。プロセスがメモリを使い果たし、さらに割り当てようとすると、割り当ては失敗します。

割り当てが失敗する理由は他にもあります。たとえば、ヒープが断片化され、割り当て要求を満たすのに十分な大きさの空きブロックが 1 つもなくなる可能性があります。

于 2013-09-08T14:42:18.577 に答える