2

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?     
4

1 回答 1

3

从析构函数中抛出是危险的,应该避免。C++ 标准库的任何对象都不会从其析构函数中抛出。C++ 语言隐含地假定析构函数被声明为noexcept.

实际上,这是std::basic_filebuf<>::close()and之间的唯一区别std::basic_filebuf<>::~std::basic_filebuf():后者调用close()但捕获任何异常而不重新抛出。因此,如果您想发现关闭基础文件的问题,您可以显式调用ofstream::rdbuf()->close(). 然而,ofstream::close()有效地调用rdbuf()->close()并捕获任何异常。在这种情况下,它会设置failbit并且如果您已相应地设置了流的异常掩码(通过ofstream::exceptions(),正如您在问题中所做的那样),则会引发类型的(不同)异常std::ios_base::failure

因此,总结一下:

  • 如果您使用 RAII(即析构函数)来关闭文件,那么即使无法完全关闭底层文件,也不会将异常传播到析构函数之外。在这种情况下,将设置故障位。
  • 如果您明确地close(),std::ofstream那么,根据流的异常掩码,std::ios_base::failure可能会在遇到关闭文件的问题时抛出。
于 2017-07-19T09:21:11.203 回答