4

私は Linux (正確には ubuntu 13.04) で作業していますが、現在質問があります: まだ十分なメモリがある場合でもメモリ割り当てが失敗するのはなぜですか?

今日、簡単なテスト アプリケーションを作成しました。このテスト アプリケーションを実行すると、この問題が発生しました。以下は、テストに使用したコードスニペットです。

     #include <stdio.h>
     #include <unistd.h>
     #include <list>
     #include <vector>
     #include <strings.h>

     using namespace std;
     unsigned short calcrc(unsigned char *ptr, int count)
     {
        unsigned short crc;
        unsigned char i;

        //high cpu-consumption code
        //implements CRC algorithm: Cylic 
        //Redundancy code              
     }


     void* CreateChild(void* param){
         vector<unsigned char*>  MemoryVector;
         pid_t PID = fork();
         if (PID == 0){
             const int MEMORY_TO_ALLOC =  1024 * 1024;
             unsigned char* buffer = NULL;
             while(1){
                 buffer  = NULL;
                 try{
                     buffer = new unsigned char [MEMORY_TO_ALLOC]();
                     calcrc(buffer, MEMORY_TO_ALLOC );
                     MemoryVector.push_back(buffer);
                 } catch(...){
                     printf("an exception was thrown!\n");
                     continue;
                 } //try ... catch
             } //while  
          } // if pid == 0

      return NULL;
      }

    int main(){
        int children = 4;
        while(--children >= 0){
            CreateChild(NULL);
        };

        while(1) sleep(3600);
        return 0;
    }

私のテスト中、約220M の RAMが利用可能になると、上記のコードは例外をスローし始めます。そして、その瞬間から、TOP コマンドによって示される空きメモリが 210M を超えたままになるため、アプリケーションはこれ以上メモリを取得できないように見えます。では、なぜこれが起こるのでしょうか?

更新
1. ソフトウェア && ハードウェア情報
RAM は4Gで、スワップは約9Gバイトです。Linux steve-ThinkPad-T410 3.8.0-30-generic #44-Ubuntu SMP Thu Aug 22 20:54:42 UTC 2013 i686 i686 i686 GNU/Linux
2. テスト中の統計データ

      Right after Test App Starts Throwing Exception
      steve@steve-ThinkPad-T410:~$ free
                    total       used       free     shared    buffers     cached
       Mem:       3989340    3763292     226048          0       2548      79728
       -/+ buffers/cache:    3681016     308324
       Swap:      9760764    9432896     327868

      10 minutes after Test App Starts Throwing Exception
      steve@steve-ThinkPad-T410:~$ free
                    total       used       free     shared    buffers     cached
       Mem:       3989340    3770808     218532          0       3420      80632
       -/+ buffers/cache:    3686756     302584
       Swap:      9760764    9436168     324596


      20 minutes after Test App Starts Throwing Exception
      steve@steve-ThinkPad-T410:~$ free
                    total       used       free     shared    buffers     cached
       Mem:       3989340    3770960     218380          0       4376     104716
       -/+ buffers/cache:    3661868     327472
       Swap:      9760764    9535700     225064

      40 minutes after Test App Starts Throwing Exception
      steve@steve-ThinkPad-T410:~$ free
                    total       used       free     shared    buffers     cached
       Mem:       3989340    3739168     250172          0       2272     139108
       -/+ buffers/cache:    3597788     391552
       Swap:      9760764    9556292     204472
4

3 に答える 3

2

アドレス空間に 1MB のシーケンシャル メモリ ページがなくなった可能性があります。空き領域の断片化があります。

于 2013-09-20T16:22:09.017 に答える
2

私のテスト中、約 220M のメモリがある場合、上記のコードは例外をスローし始めます。そしてその瞬間から、TOP コマンドで表示される空きメモリが 210M を超えたままであるため、アプリケーションはこれ以上メモリを取得できないように見えます。では、なぜこれが起こるのでしょうか?

の出力はtopN 秒 (構成済み) ごとに更新され、実際には現在のステータスは表示されません。

一方、メモリ割り当ては超高速です。

何が起こるかというと、プログラムがメモリを消費し、ある時点 (top が 200 Mb の空き容量を示しているとき) で失敗し始めます。

于 2013-09-20T16:22:15.877 に答える
0

x86-32 で実行しているため、プロセスは 32 ビットです。より多くのメモリとスワップを使用しても、アドレス空間によって制限されます。次を実行します。

grep “HIGHMEM” /boot/config-`uname -r`
grep “VMSPLIT” /boot/config-`uname -r`

カーネルがどのように構成されているかを確認します。

おそらく、4 つの子プロセスは 3G に制限されており、12G + 他のプロセスを使用して ~700M の数値に達しています。

編集:

そのため、カーネルは各ユーザー空間プロセスに 3G のアドレス空間を与えるように構成されており、その一部はプログラム、ライブラリ、初期ランタイム メモリ (フォークによって共有されます) で使用されます。

したがって、4 人の子供がそれぞれ ~3G (~12G + ~780M の他のプログラム) を使用しています。子供たちがエラーを報告し始めると、約 220M の空き領域が残ります。

別の子プロセスを実行するか、各プロセスがより多くのメモリを割り当てることができる Ubuntu の AND64/x86-64 バージョンで再インストールすることができます。

于 2013-09-24T06:42:01.540 に答える