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>
. Callsclose()
.
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, callssetstate(failbit)
(27.5.5.4) (which may throwios_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 callsclear()
,
otherwise callssetstate(failbit)
, (which may throwios_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
Why Vector≪Bool≫::Reference Doesn't Return Reference to Bool
Deleting Elements from Std::Set While Iterating
The Procedure Entry Point _Gxx_Personality_V0 Could Not Be Located
Scope Resolution Operator Without a Scope
Are Members of a C++ Struct Initialized to 0 by Default
_File_, _Line_, and _Function_ Usage in C++
How to Compile a 64-Bit Application Using Visual C++ 2010 Express
Elegant Solution to Duplicate, Const and Non-Const, Getters
Error Lnk2019: Unresolved External Symbol _Winmain@16 Referenced in Function _Tmaincrtstartup
Lock-Free Progress Guarantees in a Circular Buffer Queue
Copying a Polymorphic Object in C++
What Is the Fastest Way to Transpose a Matrix in C++
Why Can't I Use Float Value as a Template Parameter
What's a Proper Way of Type-Punning a Float to an Int and Vice-Versa