0

これは、動的に割り当てられたバッファにファイル「hello.txt」を読み込む単純なプログラムです。最初はサイズが10です(いっぱいになるとサイズが2倍になります)。

valgrindを実行すると、メモリリークが発生しているように見えますが、何が問題なのかわかりません。使用後にバッファのメモリを解放しました。

エラーは「条件付きジャンプまたは移動は初期化されていない値に依存する」のようです。

誰かがメモリリークがあるかどうかを特定するのを手伝ってもらえますか?そうでない場合、問題は何ですか?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERSIZE 10

int main(int argc, char const *argv[])
{
    FILE *source;
    source = fopen("hello.txt","r");
    char *buffer = (char *)malloc(BUFFERSIZE);

    int current_size = BUFFERSIZE;
    int len = 0;
    char c;
    while((c = fgetc(source)) != EOF)
    {
        if(len == current_size-1)
        {
            current_size *= 2;
            buffer = (char *)realloc(buffer,current_size);
        }
        buffer[len] = c;
        len++;
    }                                                                
    printf("%s",buffer);
    free(buffer);

    return 0;
}
4

5 に答える 5

3

エラーは「条件付きジャンプまたは移動は初期化されていない値に依存する」のようです。

では、なぜメモリリークについて質問しているのですか?このエラーの原因は、printf("%s", buffer)whereへの呼び出しbufferが有効な文字列ではない('\0'ターミネータがない)可能性が高いです。

コードのもう1つの問題は、の戻り値をfgetcに割り当てていることですcharchar cに変更する必要がありますint c

于 2013-01-24T19:08:42.357 に答える
1

これがvalgrindの不満である場合は、再割り当てしているバッファーにreallocの戻り値を割り当てているためです。reallocはバッファを拡張できない場合にNULLを返すため、これにより、バッファの新しい値がNULLに割り当てられ、古い値がリークされる可能性があります。

通常の比喩は次のようなものです。

char * new_buffer = realloc(buffer, current_size);
if (!new_buffer) {
    handle_error();
}
buffer = new_buffer;

また、Cでのベストプラクティスは、mallocまたはreallocからのリターンをキャストしないことです。言及する以外にここに入る価値はありません。SOには、これに答えるための専用のリソースがたくさんあります。

于 2013-01-24T19:01:58.033 に答える
0

NULLチェックが欠落しており、それらを宣言するときにNULLへのポインターを初期化しています。

valgrindオプション--track-origins=yesを使用して、初期化されていない値の原点を追跡します。これにより速度は遅くなりますが、初期化されていない値の出所を追跡するのに役立ちます。

このオプションが将来このような問題の解決に役立つことを願っています。

于 2013-01-24T19:01:35.557 に答える
0

一時ポインタを使用する必要があります。

char *temp = (char *)realloc(buffer,current_size);
if (!temp)
{
   fprintf(stderr, "Out of memory...\n");
   free(buffer);
   exit(1);
}
buffer = temp;

編集また、mallocとreallocをキャストしていることにも注意してください。これは通常、C++を使用してCをコンパイルしていることを示しています。これは理想的ではありません。IDEを使用している場合は、C ++ではなくCを使用してコードをコンパイルするように設定することをお勧めします。通常は、ファイルの名前をmyfile.cppではなくmyfile.cに変更する必要があります。変更を有効にするには、それを削除してプロジェクトに再度追加します。malloc / reallocをキャストすると、かなり厄介なバグが発生する可能性があります。

編集:バッファ内の文字列のエンドマーカーも設定していません-次のようなことを行う必要があります

buffer[len] = '\0'; 

whileループの後。ファイルが空の場合もfgetc()で「何も」得られない可能性があるため、lenがゼロになる可能性があることに注意してください。

元のmallocもNULLをチェックする必要があります。

于 2013-01-24T19:02:37.617 に答える
0

好奇心から、私はあなたのコードでMemoryScape(TotalView)を試しましたが、メモリリークは表示されません(source変数buffer参照ブロックです。つまり、これらのメモリブロックのアドレスはプログラムの現在の変数データのどこかにあります)。

I think that Valgrind is definitely showing false positive here (I don't know what leak detection algorithm is behind the scene).

于 2013-02-01T10:35:45.867 に答える