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++;
fgetsreturn description:When
fgetsdoesn’t read anything it doesn’t return thechar *that you used malloc on.Therefore, the
mallocin your last call isn’t being freed. The statement after your while doesn’t work as you want.Solution: change your return and return
lineinstead: