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函数时,我都需要调用,我这样做了。据我所知,在一个有四行的简单文本文件上,我需要免费调用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)。如果这发生在可以读取任何字符之前,则返回的指针是空指针(并且 str 的内容保持不变)。如果发生读取错误,则设置错误指示符 (ferror) 并返回空指针(但 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 回答