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.