0

大きなファイル (~412 MB) を読み取ろうとすると、ファイルの読み取りが突然停止します。プログラムは1か月間機能しましたが、今ではエラーが発生しました。何故かはわからない。助けていただけますか?Purify を使用して確認すると、プログラムにメモリ割り当てに失敗したというメッセージが表示されました。

 s.write(block, f.gcount());

大きなファイルをバッファに書き込んでいます (大きなファイルを読み込んでいます)。次に、このバッファを解析し、ファイルの次の部分を読み取ります。より少ない断片でファイルを読み取ろうとしましたが、結果は同じです。プログラムは読み取りを停止しただけで、何もしません。例外はありません (std::exception をキャッチしようとしました) 理由は何ですか? 助けてくれませんか?

ファイルは非常に単純です。

p edge 45 45

e 4 1 

e 5 6

等々

コードは次のとおりです。

   readFile(char name[]) {
       ifstream f;
       f.open(name,ifstream::binary);
       char buffer[256], token[20];
       int i, j, k, tmp;
       int vi = 0, vj = 0;
       int num_edges = 0;

       if (! f.is_open()) 
       { 
            cout << "Error opening file: " << name << endl; 
            //_getch();
        exit(1); 
       }

       strstream s;
       static const int N = 1024*1024;
       char block[N];


    while (! f.eof() ) 
    {
        s.clear();
        f.read(block, N);
        s.write(block, f.gcount());

        while (! s.eof())
        {
            s.getline(buffer, 250);
            if (s.eof())
            {
                s.write(buffer, s.gcount());
                break;
            }

            if (buffer[0] == 'c')
            {
                continue;
            }

            if (buffer[0] == 'p') 
            {
                cout << buffer << endl;
                sscanf(&buffer[7], "%d", &globalColouredVertices.size);

                if(globalColouredVertices.size > MAX_VERTICES) {
                    cout << "Too many vertices (> " << MAX_VERTICES << ")"<< endl;
                    exit(2);
                }

                //e.resize(globalColouredVertices.size);
                for (i = 0; i < globalColouredVertices.size; i++)
                {
                    globalColouredVertices.ele[i].point = i;
                }
            }
            if (buffer[0] == 'e') 
            {
                num_edges++;
                i = 2;
                j = 0;
                while ((buffer[i] >= '0') && (buffer[i] <= '9')) 
                { 
                    token[j++] = buffer[i];
                    i++; 
                }
                token[j] = '\0';
                vi = atoi(token);
                i++;
                j = 0;
                while ((buffer[i] >= '0') && (buffer[i] <= '9')) 
                { 
                    token[j++] = buffer[i];
                    i++; 
                }
                token[j] = '\0';
                vj = atoi(token);
                vi--;
                vj--;
                e[vi][vj] = 1;
                e[vj][vi] = 1;
            }

            if (num_edges % 10000 == 0)
                cout << num_edges << endl;
            else if (num_edges %  24380000 == 0) {
                cout << endl;
            }
        }
    }
 }
4

2 に答える 2

2

strstreamバッファとしての aの使用は壊れており、ほぼ確実に不要です。

このコードは、strstream に部分的な行を挿入します。したがって、後で行ごとに読むようになると、おそらく各バッファーの最後に不完全な行が表示され、次の行の開始時に別の不完全な行が表示されるでしょう。

    f.read(block, N);
    s.write(block, f.gcount());

これは、コード (特にこのスニペット、および他の人が言及したもの) に配列境界チェックがないことと相まって、これが発生するのを待っている自動車事故であることを意味します

            e[vi][vj] = 1;
            e[vj][vi] = 1;

強くお勧めします

  • a: strstream バッファを完全に削除します。
  • b: バッファを手動で割り当てる代わりに、std::vector の使用を検討してください。
  • c: その後、at()関数を境界チェック アクセスに使用できます。これにより、例外がスローされます。

それが完了するまで、最適化やパフォーマンスについて心配する必要はありません。

于 2013-02-28T13:45:01.773 に答える
1

あなたが見ている問題ではないかもしれませんが、コードには潜在的なバッファ オーバーランがいくつかあります。例えば:

while ((buffer[i] >= '0') && (buffer[i] <= '9')) 
{ 
    token[j++] = buffer[i];
    i++; 
}

インデックスがバッファ サイズを超えていないことを確認する必要があります。

于 2013-02-28T12:54:22.543 に答える