Search code examples
cfileexitmanpage

Is it good to use exit() instead of fcloseall() for closing multiple files?


The man page of exit says,

  1. All open stdio streams are flushed and closed. Files created by tmpfile are removed.
  2. Parameters of exit i.e EXIT_SUCCESS and EXIT_FAILURE are slightly more portable (to non-UNIX environments) than the use of 0 and some nonzero value like 1 or -1. In particular, VMS uses a different convention.

The man page of fcloseall says,

  1. The standard streams, stdin, stdout, and stderr are also closed.
  2. The fcloseall function does not lock the streams, so it is not thread-safe.

Many online tutorials say that deallocating "all" resources of a given type is a programming error. They should be deallocated individually by the code that owns them or not at all.

So is it good to use exit instead of fcloseall?


Solution

  • Short answer: yes, exit() is better.

    Long answer:

    It depends how you design your program. It is generally better to have each component clean up after itself, removing any temporary files and flushing buffers - this would be especially common for a C++ program where object destructors can handle this.

    In that case you would use neither exit() nor fcloseall() - you'd have your components clean up after themselves then simply return from main().

    For a C program you might prefer to design it expecting that everything will be cleaned up automatically at exit by one of these functions. If you are considering using either, then exit() is a safer bet because it will do more: it will do what fcloseall() does, plus it will remove temporary files created with tmpfile().

    In addition, fcloseall() is a GNU extension which might affect the portability of your program.

    Perhaps more importantly, these functions serve different purposes.

    The purpose of exit() is to end your program.

    The purpose of fcloseall() is to flush & close file descriptors, but not to end your program. It's perhaps most useful when you want to ensure you have closed all files (including stdin/stdout/stderr) before calling exec to start another process, without leaking any file descriptors into the new process that it will not expect and perhaps never close.