3

See the following code block, how I can make sure a FILE object is not closed before I call fclose on it? BTW, is it safe to call fclose twice?

    FILE* f = fopen('test.txt')

    //some code here, f may be closed by someone, but they may not set it to NULL
    ...


    /// I want to make sure f is not closed before, how can I do it here?
    if(...)
    {
       fclose(f)
    }
alk
  • 69,737
  • 10
  • 105
  • 255
Patrick
  • 1,283
  • 2
  • 13
  • 20

3 Answers3

7

No, you have to keep track of it yourself. This is analagous to the question of telling if a pointer to an allocated block has been freed. There could be no way to do such a test because the pointer is no longer valid. The same applies with FILE *. Once you have closed the file, any attempt to access the underlying object results in undefined behavior.

Updated:

Beware, to quote the Linux man page:

The  behaviour  of fclose() is undefined if the stream parameter is an
illegal pointer, or is a descriptor already passed to a previous invo‐
cation of fclose().

Keep in mind that undefined behavior doesn't mean that it will crash or that it won't "work". It means that no particular behavior is guaranteed and that the operation is unsafe. Accessing a FILE struct after fclose() is a very bad idea.

FatalError
  • 52,695
  • 14
  • 99
  • 116
3

Whenever you call fclose() anywhere in the program, you should set the FILE* file-pointer to NULL as follows, which you can check later during the cleanup at the end of the file.

fclose(f)
f = NULL;

The cleanup section at the end of the file would look like:

if (f != NULL)
{
    fclose(f);
    f = NULL;
}
Tuxdude
  • 47,485
  • 15
  • 109
  • 110
  • what if he is not sure the file is closed? – Aniket Inge Feb 28 '13 at 01:53
  • It is required to call fclose(FILE*) (even if the file gets deleted) to flush the buffer as well as free up any book-keeping allocated in the process for opening a file handle. It is the program's responsibility to keep track of the FILE* handle. – Tuxdude Feb 28 '13 at 01:56
  • What R. said; if it's closed and he doesn't know after he fopen'd it, then there's something deeply wrong. The filesystem doesn't open or close files, the code reading the stream does. – Russ Clarke Feb 28 '13 at 02:03
  • +1 for the only portable solution. But as for the example in this answer: Also `fclose()`might fail, so also check it's return value, as one ought to for **every** system call. – alk Feb 28 '13 at 07:20
-1

Paste fclose source code of android-bionic: (fclose.c file)

int fclose(FILE *fp)
{
    int r;

    if (fp->_flags == 0) {  /* not open! */
        errno = EBADF;
        return (EOF);
    }
    FLOCKFILE(fp);
    WCIO_FREE(fp);
    r = fp->_flags & __SWR ? __sflush(fp) : 0;
    if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
        r = EOF;
    if (fp->_flags & __SMBF)
        free((char *)fp->_bf._base);
    if (HASUB(fp))
        FREEUB(fp);
    if (HASLB(fp))
        FREELB(fp);
    fp->_r = fp->_w = 0;    /* Mess up if reaccessed. */
    fp->_flags = 0;     /* Release this FILE for reuse. */
    FUNLOCKFILE(fp);
    return (r);
}

It seems safe to call fclose on a closed FILE object.

Patrick
  • 1,283
  • 2
  • 13
  • 20
  • 1
    *"It seems safe to call fclose on a closed FILE object."* ... well... unfortunately it is not. You can drive without a seat belt and you may not get involved in an accident, but it doesn't mean it is safe. – dreamlax Feb 28 '13 at 02:55
  • @dreamlax, so what will be the bad consequence of calling fclose twice? – Patrick Feb 28 '13 at 03:43
  • @Patrick: Without more knowledge of the implementation it's difficult to say, but notice the comment saying that the FILE is being released for reuse. Imagine that same FILE struct is reused by another `fopen()` call before your second `fclose()` call. Now you inadvertently closed another file, oops... – FatalError Feb 28 '13 at 03:52
  • Any programmer that wrote a version of fclose() that doesn't have the equivalent of this *flags* variable test belongs in the same dog house as the programmer that can't remember whether the file was closed. There ought to be some room reserved for the guy that thought "r" was a good variable name btw. – Hans Passant Feb 28 '13 at 04:42
  • There are some other worlds than android. So this is no proof at all. – alk Feb 28 '13 at 07:23