In a typical example of RAII for File I/O on Wikipedia, any errors that occur when closing the file are swallowed:
#include <iostream>
#include <string>
#include <fstream>
#include <stdexcept>
void write_to_file (const std::string & message) {
// try to open file
std::ofstream file("example.txt");
if (!file.is_open())
throw std::runtime_error("unable to open file");
// write message to file
file << message << std::endl;
// file will be closed when leaving scope (regardless of exception)
}
It seems there is no way to determine if an error occurred when file
is automatically closed; obviously one can only call file.rdstate()
while file
is on scope.
I could call file.close()
manually and then check for an error, but I would have to do that at every place I return from the scope, which defeats the purpose of RAII.
Some have commented that only unrecoverable errors like file system corruption can occur within the destructor, but I don't believe that's true because AFAIK the destructor flushes the file before closing it, and recoverable errors could occur while flushing.
So is there a common RAII way to get errors that occur during destruction? I read that throwing exceptions from destructors is dangerous so that doesn't sound like the right approach.
The simplest way I can think of is to register a callback function that the destructor will call if any errors occur during destruction. Surprisingly it doesn't seem like there is an event for this supported by ios_base::register_callback
. That seems like a major oversight, unless I misunderstand something.
But perhaps a callback is the most common way to get notified of errors during destruction in modern class designs?
I assume calling an arbitrary function in a destructor is also dangerous, but perhaps wrapping the call in a try/catch
block is completely safe.
std::ofstream
closes its file upon destruction and I'm asking about how I would handle a file close error if I design a similar class myself. – Apostrophizefile
guaranteed to be flushed by the time its destructor is called? Because if not, I'm assuming that the destructor also flushes the output before closing the file, during which a recoverable error could occur. – Apostrophizeofstream
itself at least, thanks! – Apostrophizestd::basic_filebuf<...>
whose destructor callsclose
which indeed flushes the buffer. – Acoustic