Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does std::ofstream::close() actually do?

Tags:

c++

flush

fstream

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?

like image 797
NPS Avatar asked Apr 28 '13 22:04

NPS


People also ask

What is the use of close () in C++?

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.

Do I have to close ofstream C++?

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.

Do I need to close ofstream?

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.

Does C++ automatically close files?

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.


1 Answers

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.

like image 177
Alexander Shukaev Avatar answered Oct 14 '22 09:10

Alexander Shukaev