Do I Need to Close a Std::Fstream

do I need to close a std::fstream?

I think the previous answers are misleading.

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.

And while Drakosha is right that calling close gives you the possibility to check the fail bit of the stream, nobody does that, anyway.

In an ideal world, one would simply call stream.exceptions(ios::failbit) beforehand and handle the exception that is thrown in an fstream’s destructor. But unfortunately exceptions in destructors are a broken concept in C++ so that’s not a good idea.

So if you want to check the success of closing a file, do it manually (but only then).

Do I need to manually close an ifstream?

NO

This is what RAII is for, let the destructor do its job. There is no harm in closing it manually, but it's not the C++ way, it's programming in C with classes.

If you want to close the file before the end of a function you can always use a nested scope.

In the standard (27.8.1.5 Class template basic_ifstream), ifstream is to be implemented with a basic_filebuf member holding the actual file handle. It is held as a member so that when an ifstream object destructs, it also calls the destructor on basic_filebuf. And from the standard (27.8.1.2), that destructor closes the file:

virtual ˜basic_filebuf();

Effects: Destroys an object of class basic_filebuf<charT,traits>. Calls close().

Is closing fstream ( I/O ) necessary?

A std::fstream will close itself when it goes out of scope.

In your case however, the second call to std::fstream::open() fails, which sets the failbit on the stream (and could thrown an exception, but obviously doesn't in this case). With the failbit set, additional attempts to write to that stream will fail. See Return Value section here: http://www.cplusplus.com/reference/fstream/ofstream/open/

Should I close a file when it wasn't able open?

No, that's not necessary to be done explicitly. (File) streams are closed when going out of scope implicitly always.

The close() function of a std::iostream() also is an idempotent operation, and never will harm the streams state beyond the stream gets closed (or never was successfully opened).

What happens if I never call `close` on an open file stream?

There is no difference. The file stream's destructor will close the file.

You can also rely on the constructor to open the file instead of calling open(). Your code can be reduced to this:

#include <fstream>

int main()
{
std::ofstream myfile("example.txt");
myfile << "Writing this to a file.\n";
}

Closing files using fstream

Why doesn't the compiler recognize that you already closed the file?

These statements are syntactically correct, so the compiler won't complain.

Theoretically the second close() call might fail at runtime, but since its an idempotent operation, it won't.

As you can see from the reference documentation:

Notes


This function is called by the destructor of basic_fstream when the stream object goes out of scope and is not usually invoked directly.

It must even be implemented idempotentially.

Does ofstream close its files automatically?

ofstream will close files when its destructor is called, i.e. when it goes out of scope. However, calling close() certainly doesn't do any harm and expresses your intentions to maintenance programmers.

Calling close() also allows you to check if the close() was successful because you can then also check the failbit:

http://www.cplusplus.com/reference/iostream/ofstream/close/

Will forgetting to call std::ofstream close function lead to memory leak?

When your std::ofstream object goes out of scope it will automatically be closed due to the use of RAII and the automatic calling of the object destructor.

In this situation your code is perfectly acceptable and would cause no memory leaks. There is no need to call close manually at all.

Only use close if you wish to reuse the object before it goes out of scope i.e if the ofstream object was a member of a class and you wish to re-use it then its possible to call close on it and then re-open it with a different file etc.

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

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.

Explicitly saving the file using fstream without closing the file in C++

Files are often some stream of bytes, and could be much bigger than your virtual address space (e.g. you can have a terabyte sized file on a machine with only a few gigabytes of RAM).

In general a program won't keep all the content of a file in memory.

Some libraries enable you to read or write all the content at once in memory (if it fits there!). E.g. Qt has a QFile class with an inherited readAll member function.

However, file streams (either FILE from C standard library, or std::ostream from C++ standard library) are buffered. You may want to flush the buffer. Use std::flush (in C++) or fflush (in C); they practically often issue some system calls (probably write(2) on Linux) to ask the operating system to write some data in some file (but they probably don't guarantee that the data has reached the disk).

What exactly happens is file system-, operating system-, and hardware- specific. On Linux, the page cache may keep the data before it is written to disk (so if the computer loses power, data might be lost). And disk controller hardware also have RAM and are somehow buffering. See also sync(2) and fsync(2) (and even posix_fadvise(2)...). So even if you flush some stream, you are not sure that the bytes are permanently written on the disk (and you usually don't care).

(there are many layers and lots of buffering between your C++ code and the real hardware)

BTW you might write into memory thru std::ostringstream in C++ (or open_memstream in C on POSIX), flush that stream, then do something with its memory data (e.g. write(2) it to disk).



Related Topics



Leave a reply



Submit