0

Cで学習を行っていますが、メモリリークの状況を特定するのに問題があります。

まず、いくつかのコード:


の主な機能:

#define FILE_NAME "../data/input.txt"

char * testGetLine( FILE * );
int testGetCount(void);

int main(void)
{
    int count = 0;
    FILE * fptr;

    if ((fptr = fopen(FILE_NAME, "r")) != NULL) {
        char * line;
        while ((line = testGetLine(fptr)) != NULL) {            

            printf("%s", line);
            free(line); count++;
        }

        free(line); count++;

    } else {
        printf("%s\n", "Could not read file...");
    }

    // testing statements
    printf("testGetLine was called %d times\n", testGetCount());
    printf("free(line) was called %d times\n", count);

    fclose(fptr);
    return 0;
}

と私のgetline関数:

#define LINE_BUFFER 500

int count = 0;

char * testGetLine(FILE * fptr)
{
    extern int count;

    char * line;
    line = malloc(sizeof(char) * LINE_BUFFER);
    count++;

    return fgets(line, LINE_BUFFER, fptr);
}

int testGetCount(void) {
    extern int count;
    return count;
}

私の理解では、関数を呼び出すfreeたびに呼び出す必要があります。testGetLine私の計算では、4行の単純なテキストファイルで、5回無料で呼び出す必要があります。次の出力のテストステートメントでそれを確認します。

This is in line 01
Now I am in line 02
line 03 here
and we finish with line 04
testGetLine was called 5 times
free(line) was called 5 times

私が問題を抱えているのは、valgrindが私をalloc 6回言っており、 free 5回しか電話をかけていないということです。valgrindからの切り捨てられた出力は次のとおりです。

HEAP SUMMARY:
    in use at exit: 500 bytes in 1 blocks
  total heap usage: 6 allocs, 5 frees, 3,068 bytes allocated
500 bytes in 1 blocks are definitely lost in loss record 1 of 1
   at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x4007A5: testGetLine (testGetLine.c:13)
   by 0x400728: main (tester.c:16)
LEAK SUMMARY:
   definitely lost: 500 bytes in 1 blocks
   indirectly lost: 0 bytes in 0 blocks
     possibly lost: 0 bytes in 0 blocks
   still reachable: 0 bytes in 0 blocks
        suppressed: 0 bytes in 0 blocks

メモリ管理に何かが欠けているように感じます。valgrindが使用していると言う6番目のメモリ割り当てはどこにありますか?どうすれば解放できますか?


エイドリアンの答えを実装するためのフォローアップ

testGetLine調整:

char * testGetLine(FILE * fptr)
{
    extern int count;

    char * line;
    line = malloc(sizeof(char) * LINE_BUFFER);
    count++;

    if (fgets(line, LINE_BUFFER, fptr) == NULL) {
        line[0] = '\0';
    }

    return line;
}

mainwhileループ調整:

while ((line = testGetLine(fptr))[0] != '\0') {            

    printf("%s", line);
    free(line); count++;
}

free(line); count++;
4

1 に答える 1

2

fgets説明を返す:

成功すると、関数はstrを返します。文字の読み取り中にファイルの終わりが検出されると、eofインジケーターが設定されます(feof)。文字を読み取る前にこれが発生した場合、返されるポインターはnullポインターです(strの内容は変更されません)。読み取りエラーが発生した場合、エラーインジケータ(ferror)が設定され、nullポインタも返されます(ただし、strが指す内容が変更されている可能性があります)。

fgets何も読み取らない場合、 char *mallocを使用したものは返されません。

したがって、malloc最後の呼び出しのは解放されていません。whileの後のステートメントは、希望どおりに機能しません。

line解決策:返品を変更して、代わりに返品してください。

char * testGetLine(FILE * fptr)
{
    extern int count;

    char * line;
    line = malloc(sizeof(char) * LINE_BUFFER);
    count++;
    fgets(line, LINE_BUFFER, fptr);
    return line;
}
于 2013-02-03T19:11:13.713 に答える