2015-11-29 6 views
5

私はCを試し続けます。私はあなたが食べたいRAMの量を決定することができるこのプログラムを持っています。 UPDATEDCで実験する - 2GBのメモリを割り当てて使用できないのはなぜですか?

char * eatRAM() 
{ 
    unsigned long long toEat; 
    unsigned long long i = 0; 
    float input; 
    char * pMemory = NULL; 
    int megaByte = 1048576; 

    puts("How much RAM do you want to eat? (in Mega Bytes)"); 
    puts("NOTE: If you want to eat more RAM than you have available\nin your system, the program will crash"); 
    printf("\n>> MB: "); 
    scanf("%f", &input); 

    toEat = (unsigned long long)(input * megaByte); 
    pMemory = malloc(toEat); 

    printf("\n\nEating in total: %llu Bytes\n", toEat); 
    puts("Check your task manager!\n"); 

    if(pMemory != NULL) 
    { 
     printf("\n\nEating in total: %llu Bytes\n", toEat); 
     puts("Check your task manager!\n"); 

     for(i; i < toEat; i++) 
     { 
      pMemory[i] = 'x'; 
     } 
    } 
    else 
    { 
     puts("\nSeems like that amount of memory couldn't be allocated :(\n"); 
    } 
    return pMemory; 
} 

QUESTION:事は、私は例1024メガバイトのために入力した場合、それが動作すること...ある

、私はそれが1GBのRAMを使用しているタスクマネージャで見ることができます。私は1500メガバイトそれが動作します。..

を入力してくださいしかし、私は2048メガバイトを入力する場合、それは言っても

を割り当てることができませんでした:(

またはメモリの量のことのように思えます私が入力しても1756MB

私はC言語に新しいです、多分私は何か重要なrelat OSがメモリにアクセスする方法を教えてください。何がで​​きるのですか?

+0

malloc関数は、おそらくあなたはそれを使用しようとする前に、 'pMemory!= NULL'をチェックする必要があり、失敗し、割り当てが失敗したものの、メモリにアクセスしようとするため、ヌル、確認することを –

+0

クラッシュを返します。また、 'malloc()'をキャストすべきではありません。通常は 'void *'から他のポインタにキャストしないでください。 –

+0

あなたのコンピュータにはどのくらいのRAMがありますか? –

答えて

5

Windows上の32ビットプロセスでは、デフォルトで2ギガバイトのアドレス空間が使用可能です。完全なpow(2,32)アドレス空間の下半分、オペレーティングシステムで上位2 GBが使用されます。誰も32ビットOSを使わないので、あなたのプログラムを/ LARGEADDRESSAWAREとリンクさせると4 GBを得ることができます。

2 GBのVMスペースは、コードとデータで共有する必要があります。お使いのプログラムは通常0x00400000でロードされ、使用するオペレーティングシステムのDLL(kernel32.dllやntdll.dllなど)には負荷の高いアドレス(0x7F000000を超える)があります。少なくとも起動スレッドのスタックとデフォルトのプロセスヒープは、プログラムの実行が開始される前に作成されますが、そのアドレスは一般的に予測できません。

あなたのプログラムでは、アンチマルウェア、クラウドストレージなどの「サービス」を提供注射したDLLがあるでしょう、シュリンクラップするいずれかのOSがインストールほとんどの中のウイルスの攻撃を受けることになります。これらのDLLのロードアドレスは予測できません。また、あなた自身とリンクし、プログラムの起動時に暗黙的にロードされるDLLもあります。いくつかのプログラマーが優先ベースアドレスに注意を払い、デフォルトの0x1000000のままにしておきます。これらのDLLは、デバッガの[Modules]ウィンドウから参照できます。このようなDLLは、しばしば独自のCRTを持ち、独自のヒープを作成する傾向があります。あなた自身を作る

割り当て、低断片化ヒープから来ることはありません、特に非常に大規模なものは、既存のコードとデータの割り当ての間に残された穴にアドレス空間を見つける必要があります。あなたが1500 MBを取得した場合、あなたのVMはかなりきれいです。一般的に650 MBを超える問題に遭遇し、プログラムがしばらく実行されていて、VM領域を断片化してしまった場合、すぐに少なくなります。あなたは十分なVMが残っていないので、OSが十分大きな穴を見つけることができないので、割り当ての失敗はほとんど常に発生します。ホールの合計は、失敗した割り当て要求よりもかなり大きい場合があります。

これらの詳細は、急速に昔話になっている、まだのx86をターゲットにする非常に少数の残りの理由があります。ターゲットx64とアドレス空間の断片化は今後20年間は問題ではなく、8TBのVMを断片化することは非常に困難です。それを超えて成長するためのヘッドルームがたくさんあります。

なぜ、2048 MBを得ることができないのかはっきりしているはずです。すべてを得ることはできません。 SysInternalsのVMMap utilityから詳しい情報を入手すると、VMがどのように刻まれているかがわかります。そしてMark Russinovichのblog postと本はたくさんのバックグラウンドを与えます。

+0

このようなうまくサポートされた回答をいただきありがとうございます!研究と練習を続けよう! - 乾杯! –

0

空きメモリの残量が割り当てようとしている量より少ない場合、割り当ては機能しません。

また、右側のこの行の後:

pMemory = (char *) malloc(toEat); 

は、以下を追加します。代わりに "セグメンテーション違反" 関連のメッセージを受信する、

if (!pMemory){ 
    printf("Can't allocate memory\n"); 
    return NULL; 
} 

そのように、あなたは一つの「缶」表示されますt allocate memory "というメッセージが返され、関数はNULLを返します。

eatRam関数を呼び出す関数で同様の値チェックが行われていることを確認するか、「セグメント化エラー」メッセージが表示されます。また、gdbのようなデバッガを使用してください。

+1

マイクにお返事ありがとうございます。実際には2048MBのテストを実行するときに5GB以上の空きRAMがありますが、どう思いますか?また、mallocの戻り値を適切に処理できるように、私のコードを数分前に更新しました。再度、感謝します! –

+2

@JuanBonnettあなたが使用しているメモリが1つの巨大なコードブロックであることを意味することに注意してください.2GB以上の空きメモリがあっても1GBの空きブロックはありません。また、私はこの理由のために、ウィンドウにはいくつかの "ブロック制限"があるので、アプリケーションは他のアプリケーションやそのようなものからメモリを割り当てようとはしません。 – TomTsagk

3

C制限ではなくOS制限です。

4Gb以上のシステムに対応するには、64ビットOSを実行する必要があり、1つのプロセスで4Gb以上を処理するには、64ビットアプリケーションとして構築する必要があります。 Win32には2Gbのプロセスメモリがあります。 5Gbの物理RAMは、メモリが仮想化されているため、ほとんど無関係です。

32ビットおよび64ビットのシステムとアプリケーションの理論的な限界を除いて、OSは依然として制限を課す可能性があります。 Windowsの異なるバージョンとエディション(Home、Pro、Serverなど)は、商業上の理由から、特定の制限を課しています。

具体的な回答には、システム、ツールチェーン、およびビルドオプションが適用されている必要があります。 WindowsおよびVC++を使用している場合は、/LARGEADDRESAWAREオプションを検討する必要があります。デフォルトでは32ビットコンパイラでは有効になっていませんが、physical address extensionが有効になっている場合を除き、いずれの場合でもWin32では2Gbのデフォルト制限があります。

私は、Win64上で実行されている32ビットプロセスが完全な4Gb 32ビットアドレス空間を扱うことができると確信していますが、その場合は確かに/LARGEADDRESAWAREでビルドする必要があります。それでも、すべてのスペースがヒープで利用可能であるとは限らず、単一の割り当ては連続していなければならないため、以前の割り当てとヒープの断片化によって制限される可能性があります。

+0

このようなうまくサポートされた回答をいただきありがとうございます!研究と練習を続けよう! - 乾杯! –

関連する問題