2013年8月16日金曜日

Linuxプログラムのメモリ不足

人の作ったプログラム何ですが、やたらとmalloc(正確にはcallocの方)を使ったCプログラムがありました。それの動きがどうもおかしい(不安定)なんで、見てみると数百MBのデータファイルを最初に読み込ませていました。(データファイルの大きさは、利用する状況によって変わります)動いているマシンが、RHEL6 32bitとのことなんで、明らかにmallocに失敗していると思われます。
ところが、このプログラムmallocの結果を全然チェックしておらず、catchもしていません。またプログラムを使っている人たちもLinuxに関しては素人ということで、何が悪いのか理解させるのに一苦労。試しにちょっとサンプルプログラムを作って見ました。


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MALLOC_SIZE 100000

int main()
{
  int i,j;
  int *pt;

  for (i=0; i<10000; i++) {
    pt = (int *)calloc( MALLOC_SIZE, sizeof(int));
    if (pt == NULL) {
      printf("## calloc error!! i= %d ##\n", i);
      exit(0);
    }

    for (j=0; j<MALLOC_SIZE; j++) {
      pt[j] = i;
    }

  }

}

取得したメモリに値を書き込んでいるのは、こうして実際に何か使わないと、それまでは本当にメモリの取得につながらないからです。(最初、これで苦労しました)

さてこれで実行してみるとerrorが出たときの、iの値は8,017、あれ?毎回400KB近くのメモリを取得しているはずなのに、これだと3.2GBのメモリを取得したことになっちゃうぞ?確か、Linuxだと1プロセスの最大サイズは2GB弱で、そのうちStackが1GB、Heapが700MBくらいだったはず。おおすぎます。
そこでValgrindでチェックしてみると、i=6,910 2.764GBのheap要求がされたとのこと。(計算が合う)再度、ぐぐりましたが、どうも1プロセスでのサイズ制限はなくなり、4GBのどの空間をKernel用、Stack用、Heap用に用途わけするようになったみたいです。
マシンを占有できれば大きなプログラムを動かせますが、動作解析が更にやっかいになったようです。



0 件のコメント:

コメントを投稿