FILE *file = fopen(argv[1], "r");
if(file != NULL){
char command[MAX_BUFFER];
while(fgets(command, MAX_BUFFER, file) != NULL){ //read line
//operations
}
fclose(file);
}
else write(fileno(stderr), ERROR_MESSAGE, strlen(ERROR_MESSAGE));
I’m working on a pretty basic UNIX shell implementation that reads and executes line by line from a file. From the above code, I’m trying to figure out why fclose() might fail since valgrind seems to be telling me that I’ve left this file descriptor open.
Am I correct in assuming that the “still reachable” 568 bytes in the leak summary refer to a failed fclose() somehow?
==25428== FILE DESCRIPTORS: 4 open at exit.
==25428== Open file descriptor 3: test
==25428== at 0x4F186B0: __open_nocancel (syscall-template.S:82)
==25428== by 0x4EAC628: _IO_file_fopen@@GLIBC_2.2.5 (fileops.c:233)
==25428== by 0x4EA1265: __fopen_internal (iofopen.c:93)
==25428== by 0x400C0C: main (in /home/Desktop/sh)
==25428==
==25428== Open file descriptor 2: /dev/pts/0
==25428== <inherited from parent>
==25428==
==25428== Open file descriptor 1: /dev/pts/0
==25428== <inherited from parent>
==25428==
==25428== Open file descriptor 0: /dev/pts/0
==25428== <inherited from parent>
==25428==
==25428== LEAK SUMMARY:
==25428== definitely lost: 0 bytes in 0 blocks
==25428== indirectly lost: 0 bytes in 0 blocks
==25428== possibly lost: 0 bytes in 0 blocks
==25428== still reachable: 568 bytes in 1 blocks
==25428== suppressed: 0 bytes in 0 blocks
Your visible code looks ok.
But to answer your question: likely, but the problem is somewhere else 😉
To debug your program, comment out ‘operations’, so you have an empty loop.
Does valgrind still complain ?
No: the problem very likely lies within the code you named ‘operations’.
Remove the comments and compile with debugging symbols on (-g) and use valgrind with these options:
valgrind –leak-check=yes –show-reachable=yes –track-origins=yes yourprogram
Yes: (very unlikely) something else got smashed, try to valgrind with more commented code.
To find bugs at compile time, use the compiler’s flags (e.g. gcc has -Wall -Wextra -Wwrite-strings -Wformat=2 -Wformat -Wformat-security -D_FORTIFY_SOURCE=2 and more).
And make use of static analysers e.g. llvm/clang (compile with clang –analyze yourprogram.c)