2016-12-21 8 views
-1

私はCで作成した関数を使って.csvファイルからダブルデータを読み込もうとしています。 私は100000000行と20列(ファイルサイズ約14.5 GB)私は何の問題もありませんでしたが、たとえば200000000行と20列の大きなファイルを挿入すると、セグメンテーション違反が発生します。 私は52 GBのメモリを持つシステムでプログラムを実行しているので、これらのファイルには十分な大きさです。 私はコンパイルのために: gcc read_files.c -D_FILE_OFFSET_BITS = 64 実行前にも私はulimit -a unlimitedを使用しました。Cで巨大なCSVファイルを読み取る

コードは次のとおりです。多くのテストの後

double** file_read(char *filename,int *numObjs,int *numCoords,int line_length, int lines_to_skip,int attr_to_skip) 
{ 
    double **objects; 
    long int  i, j, len; 
    ssize_t numBytesRead; 
    int done=0; 
    FILE *infile; 
    char *line, *ret; 
    char * pch; 

    if ((infile = fopen(filename, "r")) == NULL) { 
      fprintf(stderr, "Error: no such file (%s)\n", filename); 
      return NULL; 
    } 

    line = (char*) malloc(line_length); 

    len = (*numObjs) * (*numCoords); 

    objects = (double**)malloc((*numObjs) * sizeof(double*)); 
    objects[0] = (double*) malloc(len * sizeof(double)); 
    for (i=1; i<(*numObjs); i++) 
     objects[i] = objects[i-1] + (*numCoords); 

    for(i=0;i<lines_to_skip;i++) 
     fgets(line, line_length, infile); 

    i=0; 
    j=0; 

    while (fgets(line, line_length, infile) != NULL && i<*numObjs) 
    {  
      pch=strtok(line, ",;"); 
      while (pch != NULL && j<(*numCoords)) 
      { 
       objects[i][j]=atof(pch); 
       pch = strtok (NULL, ",;"); 
       j++; 
      } 
      i++; 
      j=0; 
      done=0; 
    } 


    fclose(infile); 
    free(line); 


    return objects; 
} 

、私はセグメンテーションフォールトがwhileループ内で発生したことを確信しているが、私は理由を理解することはできません。何か案は? ありがとうございます

+0

'malloc'からの戻り値をチェックするのが賢明かもしれません。 –

+0

Valgrindのようなメモリ使用アナライザの下でプログラムを実行することを検討してください。ファイルのディスク上の表現よりも多くのメモリをプログラムが使用していることがわかります。 Valgrindはそれについて教えてくれるし、あなたに影響を与えている可能性のあるメモリリークについても警告します。 –

+0

'malloc'が有効なメモリブロックを返すかどうかをチェックせず、なぜクラッシュをコード化するのか不思議です。私はそのような質問に答えることを拒否します。 – Olaf

答えて

3

整数オーバーフローがあります。私は、あなたがそうでなければ、メモリの計算のために

long int len; 

を使用するために必要なていないので、あなたのintは、32ビットでなければならないと推定

len = (*numObjs) * (*numCoords); 

あなたが提供する数字から計算が200000000 * 20 = 4000000000です。すなわち、int計算(オペランドのタイプ)として実行される前lenに割り当てられ、そして生成物を32ビットintの範囲外です。

len = (long int)(*numObjs) * (*numCoords); 

をかunsignedタイプを使用します。

あなたは最初のオペランドの1をキャストする必要があります。

+0

また、引数が 'size_t *'に渡され、 'len'が' size_t len; 'として定義されるようにしてください。 –

関連する問題