How to detect unclosed file handles in C/C++

Sometimes we forget to close file handles which are no longer required in the program. This might eventually eat up some useful resources like open file count, memory, etc. Valgrind does magic at checking a variety of such leakages. All you need is run the program under Valgrind with –track-fds option. Here is the output of a simple C program, executed under Valgrind, which opens a file handle but doesn’t close it.

$ gcc -Wall -g -o fopen fopen.c
$ valgrind --tool=memcheck --leak-check=full --track-fds=yes ./fopen
==2771== Memcheck, a memory error detector
==2771== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==2771== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==2771== Command: ./fopen
==2771== 
File opened successfully
==2771== 
==2771== FILE DESCRIPTORS: 4 open at exit.
==2771== Open file descriptor 3: /tmp/fl
==2771==    at 0x4125F73: __open_nocancel (syscall-template.S:82)
==2771==    by 0x40B9ACB: _IO_file_open (fileops.c:233)
==2771==    by 0x40B9C87: _IO_file_fopen@@GLIBC_2.1 (fileops.c:338)
==2771==    by 0x40ADD86: __fopen_internal (iofopen.c:93)
==2771==    by 0x80484F7: main (fopen.c:23)
==2771== 
==2771== Open file descriptor 2: /dev/pts/0
==2771==    
==2771== 
==2771== Open file descriptor 1: /dev/pts/0
==2771==    
==2771== 
==2771== Open file descriptor 0: /dev/pts/0
==2771==    
==2771== 
==2771== 
==2771== HEAP SUMMARY:
==2771==     in use at exit: 352 bytes in 1 blocks
==2771==   total heap usage: 1 allocs, 0 frees, 352 bytes allocated
==2771== 
==2771== LEAK SUMMARY:
==2771==    definitely lost: 0 bytes in 0 blocks
==2771==    indirectly lost: 0 bytes in 0 blocks
==2771==      possibly lost: 0 bytes in 0 blocks
==2771==    still reachable: 352 bytes in 1 blocks
==2771==         suppressed: 0 bytes in 0 blocks
==2771== Reachable blocks (those to which a pointer was found) are not shown.
==2771== To see them, rerun with: --leak-check=full --show-reachable=yes
==2771== 
==2771== For counts of detected and suppressed errors, rerun with: -v
==2771== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

As you can see, at the end Valgrind prints a list of all open file descriptors and stack trace showing where the file was opened.

Leave a Reply

Your email address will not be published. Required fields are marked *