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?
Other than flushing the userspace buffers, i.e. flush()
, close(2)
is called on the underlying file-descriptor. It depends on the operating system what happens then, but most likely nothing happens to the actual storage occupied by the file.
What will happen is that the (if the file descriptor was the last reference in that process to that file) file entry associated with the file gets removed from the open-file table of the process. I.e. freeing process-associated kernel-memory.
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.
Closes the file currently associated with the object, disassociating it from the stream.
Any pending output sequence is written to the file.
If the stream is currently not associated with any file (i.e., no file has successfully been open with it), calling this function fails.
The file association of a stream is kept by its internal stream buffer:
Internally, the function calls rdbuf()->close(), and sets failbit in case of failure.
Note that any open file is automatically closed when the ofstream object is destroyed.
From: http://www.cplusplus.com/reference/fstream/ofstream/close/