Do I Need to Manually Close an Ifstream

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().

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).

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).

will ifstream cause memory leak if I don't close?

No. fstream is an RAII object, it does close automatically at the end of the scope. Which means it is eventually closed for you in any way.

You can, however, close it manually by explicitly calling close or simply nest it in scope using curly-braces {}.

Another situation arises, if you want to check, if the closing of the file succeeded. Than you also have to call it manually. This is useful if you want to guarantee a point in the code where the file is complitly written.

Also make sure to check out cppreference for further information.

The linux man-page for close states the following, which is also interesting to read

Not checking the return value of close() is a common but nevertheless serious programming error. It is quite possible that errors on a previous write(2) operation are first reported at the final close(). Not checking the return value when closing the file may lead to silent loss of data. This can especially be observed with NFS and with disk quota.

A successful close does not guarantee that the data has been successfully saved to disk, as the kernel defers writes. It is not common for a filesystem to flush the buffers when the stream is closed. If you need to be sure that the data is physically stored use fsync(2). (It will depend on the disk hardware at this point.)

It is probably unwise to close file descriptors while they may be in use by system calls in other threads in the same process. Since a file descriptor may be reused, there are some obscure race conditions that may cause unintended side effects.

I am not sure about the situation of flush on windows. Maybe someone can add this information.

Further close() guarantees to throw an exception on failure which you can catch and handle.

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/

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 ifstream::close reset failbit and/or badbit?

close() should not clear any of the state flags, although it might set failbit depending on the return value of the underlying buffer.

[fstream.members] (also [ifstream.members] and [ofstream.members])

void close();

Effects: Calls rdbuf()->close() and, if that function returns returns a null pointer, calls setstate(failbit) (27.5.5.4) (which may throw ios_base::failure).

The flags are cleared by open() however, assuming the filebuf opens correctly

void open(const char* s, ios_base::openmode mode =
ios_base::in|ios_base::out);

Effects: Calls rdbuf()->open(s,mode).
If that function does not return a null pointer calls clear(),
otherwise calls setstate(failbit), (which may throw ios_base::failure)
(27.5.5.4).

Why is std::ifstream closing by itself?

The expression strerror(File.rdstate()) is not meaningful. The expression File.rdstate() returns an integer which represents the bits of the state flags of the stream. This is not an error code. However, the function strerror expects an error code.

Therefore, calling strerror(errno) or perror(nullptr) may be more meaningful, in general. But in this case, both just return or print "No Error".

In your question, you wrote:

It reads the first name on the list successfully, but when it tries to read the second name, it doesn't hit the delimiting char, and for some reason it leads to the file closing by itself. I hope someone can explain to me why does this happen.

The file does not close. The error message

No such file or directory

that you are receiving is misleading. It is a result of your incorrect usage of the function strerror, as described above.

What happens is that if getline is unable to read the deliminating character, it causes the failbit to be set. Due to the stream being in a failed state, the next function call of getline in the next loop iteration immediately fails without attempting to extract any characters. This causes the if statement

if (strlen(Buffer) == 0)

to be true, causing the loop to be aborted.

ofstream - need to delete object handle after close() operation?

Yes you have to. In C++ you must pair new and delete.

Though, in a simple case like this you don't need to, you can allocate your object on the stack and it will be destroyed for you, this is strongly recommended (faster and safer):

{ // enclosing scope (function, or control block)
ofstream mFileStream(LogPath.c_str(), std::ios::trunc);
...
mFileStream.close(); // mFileStream is not a pointer any more, use the "." operator
// mFileStream destroyed for you here. "close" may even be called for you.
}

Small note: it is close with a small "c".



Related Topics



Leave a reply



Submit