简体   繁体   中英

C Memory leaks and Valgrind output

I am doing some learning with C, and am having trouble identifying a memory leak situation.

First, some code:


My main function:

#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;
}

and my getline function:

#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;
}

my understanding is that I would need to call free everytime I have called my testGetLine function, which I do. By my count, on a simple text file with four lines I need to call free 5 times. I verify that with my testing statements in the following output:

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

What I am having trouble with is, valgrind says that I alloc 6 times, and am only calling free 5 times. Here is truncated output from 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

I feel I am missing something with the memory management. Where is the 6th memory allocation that valgrind says I am using? and how should I free it?


Followup to implement Adrian's answer

testGetLine adjustment:

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;
}

main while loop adjustment:

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

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

free(line); count++;

fgets return description:

On success, the function returns str. If the end-of-file is encountered while attempting to read a character, the eof indicator is set (feof). If this happens before any characters could be read, the pointer returned is a null pointer (and the contents of str remain unchanged). If a read error occurs, the error indicator (ferror) is set and a null pointer is also returned (but the contents pointed by str may have changed).

When fgets doesn't read anything it doesn't return the char * that you used malloc on.

Therefore, the malloc in your last call isn't being freed. The statement after your while doesn't work as you want.

Solution: change your return and return line instead:

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

    char * line;
    line = malloc(sizeof(char) * LINE_BUFFER);
    count++;
    fgets(line, LINE_BUFFER, fptr);
    return line;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM