2

私はcが初めてです。Cudaでテストしようとしているコードがいくつかありますが、データを取り込むのに少し問題があります.私のデータはファイル(19GB)にあり、基本的に特定の行数を読み取ってリストに保存し、それらを処理して、ファイル全体に対してこれを繰り返します。

私はこれを行う方法を学び始めたばかりで、よくわからないCの問題があります。プログラムを実行すると、メモリが増加し続けます(Macでアクティビティモニターに移動すると)が、 cプログラムに関連付けられているようには見えません。非アクティブなメモリがどんどん増えていることを示しているだけです。プログラムが停止した後でも、メモリはまだ非アクティブです (元に戻す唯一の方法は再起動することです)。私が知る限り、それはプログラムに影響を与えませんが、奇妙に思えます。その理由と、それについてできるかどうか/何ができるか知りたいですか?

line私は malloc と free について少し理解しています (申し訳ありませんが、Java/Python をよく知っていて、これを行う必要はありませんでした) が、変数が上書きされ続けていると思ったため、このコードでそれを行うべきかどうかわかりません。

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

int main() {
    printf("Starting..");
    char line[1024];
    FILE *fp = fopen("output.txt","r");

    if( fp == NULL ) {
        return 1;
    }
    int count = 0;
    while( fgets(line,1024,fp) ) {
        //printf("%s\n",line);
        count++;
    }
    printf(" num of lines is %i \n", count);

    return 0;
}

ここで何が起こっているかについてのヒントや提案をいただければ幸いです。これを行うためのより良い方法はありますか?

更新: 申し訳ありませんが、言及していませんでした。私が気付いた動作は、プログラムの実行中です。それが実行されると、非アクティブなメモリは成長し続けます。約 4 ギガバイトの空き容量があり、30 秒後にすべてがいっぱいになり、再起動することが唯一の解放方法です (c プログラムが強制終了された場合でも、メモリは解放されません)。

4

3 に答える 3

2

コードは (構造体のメモリを除いてFILE) メモリを割り当てないため、ファイル サイズに依存するリークは発生しません。

ただし、ファイルへのアクセスが完了した後に忘れたため、メモリリークが発生します。fclose(fp);

提案として、Linux を使用している場合はvalgrind --leak-check=full ./yourapp、プログラムがデバッグ シンボル (gcc のスイッチ) を使用してコンパイルされていると仮定すると-g、プログラムがメモリをリークしているかどうか、またはどこでリークしているかを正確に示す詳細なリーク レポートが得られます。

于 2012-05-31T00:53:12.810 に答える
2

これは完全に正常です。メモリを解放するには手間がかかります。メモリが必要になるとすぐに、システムはメモリを空きプールから削除する必要があるため、この作業は完全に無駄になります。メモリをある用途から別の用途に直接移行する方がはるかに効率的です。そのため、システムはばかげているのではなく、スマートになっています。

今日半分のメモリを使用しても、明日は 2 倍のメモリを使用できるわけではありません。したがって、メモリを解放してもメリットはありません。

ファイルから行を読み取る場合、オペレーティング システムはファイルからブロック全体を読み取ります。可能であれば、これらのブロックをメモリに保持しようとします。これにより、将来ディスクから読み取る必要がなくなるためです。メモリを配置するより良い用途がない場合、それらのファイル ブロックをメモリに保持します。これにより、メモリを再度使用するためだけにメモリを解放する手間が省け、ファイルの同じブロックへの今後のアクセスが高速化されます。

このメモリを解放してもメリットはありません。OS側でそれを解放するために努力し、OS側でそれを将来再び使用できるようにする努力が必要であり、OSはディスクの読み取りを回避する機会を失います. したがって、メモリを解放することは完全に愚かなことです。

于 2012-05-31T01:03:11.553 に答える
1

それはあなたが使っているからです

    fgets(buffer, int size, file);

これは、EOF にヒットした場合にのみ読み取りを停止します。それを修正するには2つの方法があります。

    while(fgets(buffer, size, file) != EOF){};

また

    while(fread(buffer, sizeof(char), nmem, file) < 1024){};

後者を使用することをお勧めします。何らかの理由で fgets を使用すると問題が発生する傾向があり、fread を使用して行うことをより細かく制御できます。

于 2012-05-31T01:21:39.693 に答える