This question: How to protect log from application crash? has lead me to another - what does std::ofstream::close()
actually do? I know it calls flush()
and that's one thing. But what else? What closing the file actually is?
Edit:
Let me rephrase my question - is anything physically done to the actual file during the call to close()
or is it just std::ofstream
internal cleanup stuff?
close(): This function helps to close an existing file. get(): This function helps to read a single character from the file. put(): This function helps to write a single character in the file.
fstream is a proper RAII object, it does close automatically at the end of the scope, and there is absolutely no need whatsoever to call close manually when closing at the end of the scope is sufficient. In particular, it's not a “best practice” and it's not necessary to flush the output.
So no, we do not need to explicitly call fstream::close() to close the file. After open a file with fstream/ifstream/ofstream, it is safe to throw an exception without manually close the file first. When the fstream/ifstream/ofstream object is out of scope, the file will be closed automatically.
C++ File I/O Closing a file Explicitly closing a file is rarely necessary in C++, as a file stream will automatically close its associated file in its destructor. However, you should try to limit the lifetime of a file stream object, so that it does not keep the file handle open longer than necessary.
Here is the trace of calls from documentation:
void std::basic_ofstream::close();
Effectively calls rdbuf()->close()
. If an error occurs during operation, setstate(failbit)
is called.
std::basic_streambuf<CharT,Traits>* std::basic_ofstream::rdbuf() const;
Returns the associated stream buffer. If there is no associated stream buffer, returns NULL
.
std::basic_streambuf
actually inherits std::basic_filebuf
, therefore:
std::basic_filebuf<CharT, Traits>* std::basic_filebuf::close();
If a put area exist (e.g. file was opened for writing), first calls overflow(Traits::eof())
to write all pending output to the file, including any unshift sequences.
If the most recently called function, out of underflow()
, overflow()
, seekpos()
, and seekoff()
, was overflow()
, then calls std::codecvt::unshift()
, perhaps multiple times, to determine the unshift sequence according to the imbued locale, and writes that sequence to file with overflow(Traits::eof())
.
Then, closes the file as if by calling std::fclose
, regardless of whether any of the preceding calls succeeded or failed.
NOTE: close()
is typically called through the destructor of std::basic_filebuf
(which, in turn, is typically called by the destructor of std::basic_fstream
.
First of all, we can see that it doesn't actually call flush()
directly as you expected. Nevertheless, the flushing effect indeed occurs in the std::basic_filebuf::close()
method. In addition, we can see that it still does a bit of tampering with a file, i.e. writing the unshift sequence. Nothing else special happens then, the file simply closes.
Pay attention to the NOTE above: in most cases you don't even need to call std::basic_ofstream::close()
explicitly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With