4

Can a file stream destructor throw an exception, e.g., if file closing operation fails?

   auto f = new std::ofstream("data.txt");
   f->exceptions(std::ofstream::failbit | std::ofstream::badbit);
   ...
   delete f; // May throw?     

Can I prevent such exceptions by closing a stream manually?

   auto f = new std::ofstream("data.txt");
   f->exceptions(std::ofstream::failbit | std::ofstream::badbit);
   ...
   f->close();
   delete f; // May throw?     
Daniel Langr
  • 22,196
  • 3
  • 50
  • 93

1 Answers1

4

Throwing from a destructor is dangerous and should be avoided. No object of the C++ standard library throws from its destructor. The C++ language implicitly assumes that destructors are declared as noexcept.

In fact, this is the only difference between std::basic_filebuf<>::close() and std::basic_filebuf<>::~std::basic_filebuf(): the latter calls close() but catches any exception without re-throwing. So, if you want to catch problems with closing the underlying file, you could explicitly call ofstream::rdbuf()->close(). However ofstream::close() effectively calls rdbuf()->close() and catches any exceptions. In this case, it sets the failbit and iff you have set the stream's exception mask accordingly (via ofstream::exceptions(), as you did in your question) throws a (different) exception of type std::ios_base::failure.

Thus, to summarize:

  • if you use RAII (i.e. the destructor) to close the file, no exceptions will be propagated out of the destructor, even if the underlying file could not be closed cleanly. In this case, the failbit will be set.
  • if you explicitly close() the std::ofstream, then, depending on the exception mask of the stream, std::ios_base::failure may be thrown upon encountering a problem with closing the file.
Walter
  • 44,150
  • 20
  • 113
  • 196