What happens to the data inserted into an unopen stream? - c++

My intuitive feeling is that the data is thrown away entirely. I cannot seem to find a source with which to verify this suspicion.
What happens to data inserted into an unopen stream? (eg. std::ofstream)
Is the data discarded? Perhaps it is stored in a buffer until the stream is opened? Perhaps something else?

In the standard "remarks" of all the file stream buffer methods that correspond to operations on the buffer it indicates that if is_open() == false, the function always fails. Failure is defined as returning traits_type::eof(). This special value is caught by higher-level IO functions which in turn set std::ios_base::badbit flag in the stream state.

If the output stream is in a fail state (eg.: not open) nothing happens to the stream - the request to output/buffer data is ignored entirely.
Note: If the exception std::ios_base::badbit is enabled, it will be thrown.

Related

What is the difference between flush() and sync() in regard to fstream buffers?

I was reading the cplusplus.com tutorial on I/O. At the end, it says fstream buffers are synchronized with the file on disc
Explicitly, with manipulators: When certain manipulators are used on
streams, an explicit synchronization takes place. These manipulators
are: flush and endl.
and
Explicitly, with member function sync(): Calling
stream's member function sync(), which takes no parameters, causes an
immediate synchronization. This function returns an int value equal to
-1 if the stream has no associated buffer or in case of failure. Otherwise (if the stream buffer was successfully synchronized) it
returns 0.
in addition to a few other implicit cases ( such as destruction and stream.close() )
What is the difference between calling fstream::flush() and fstream::sync()? endl?
In my code, I've always used flush().
Documentation on std::flush():
Flush stream buffer
Synchronizes the buffer associated with the stream
to its controlled output sequence. This effectively means that all
unwritten characters in the buffer are written to its controlled
output sequence as soon as possible ("flushed").
Documentation on std::streambuf::sync():
Synchronize input buffer with source of characters
It is called to synchronize the stream buffer with the controlled sequence (like the file in the case of file streams). The public member function pubsync calls this protected member function to perform this action.
Forgive me if this is a newbie question; I am a noob.
basic_ostream::flush
This is a non-virtual function which writes uncommited changes to the underlying buffer. In case of error, it sets an error flag in the used stream object. This is because the return value is a reference to the stream itself, to allow chaining.
basic_filebuf::sync
This is a virtual function which writes all pending changes to the underlying file and returns an error code to signal success or failure.
endl
This, when applied to an ostream, writes an '\n' to the stream and then calls flush on that stream.
So, essentially: flush is a more general function for any stream, whereas sync is explicitly bound to a file. flush is non-virtual, whereas sync is virtual. This changes how they can be used via pointers (to base class) in the case of inheritance. Furthermore, they differ in how they report errors.
sync is a member of input streams, all unread characters are cleared from the buffer. flush is a member of output streams and buffered output is passed down to the kernel.
C++ I/O involves a cooperation between a number of classes: stream, buffer, locale and locale::facet-s.
In particular sync and flush are member function that exist in both stream and streambuf, so beware to what documentation you are referring, since they do different things.
On streams flush tells the stream to tell the buffer (note the redirection) to flush its content onto the destination. This makes sure that no "pending write" remains.
std::endl, when applied to thestream with <<, is no more than a
thestream.put('\n'); thestream.flush();
Always on streams, sync tells the stream to tell the buffer to flush the content (for output) and read (for input) as much as it can to refill the buffer.
Note that -in buffers- sync can be also called internally by overflow to handle the "buffer full" (for output) and "buffer empty" (for input) situations.
I thus sense, sync is much more an "internal" function used in stream to buffer communication and buffer implementation (where it is virtual and overridden in different buffer types), while flush is much more an interface between the stream and the client program.
endl ... is just a shortcut.
I've understood it to be as follows:
flush() will get the data out of the library buffers into the OS's write buffers and will eventually result in a full synchronization (the data is fully written out), but it's definitely up to the OS when the sync will be complete.
sync() will, to the extent possible in a given OS, attempt to force full synchronization to come about — but the OS involved may or may not facilitate this.
So flush() is: get the data out of the buffer and in line to be written.
sync() is: if possible, force the data to be definitively written out, now.
That's been my understanding of this, but as I think about it, I can't remember how I came to this understanding, so I'm curious to hear from others, too.
What is the difference between calling fstream::flush() and fstream::sync()?
There is none: Both essentially call rdbuf()->pubsync() which then calls std::streambuf::sync(), see links at https://en.cppreference.com/w/cpp/io/basic_fstream
After constructing and checking the sentry object, calls rdbuf()->pubsync()
and https://en.cppreference.com/w/cpp/io/basic_streambuf/pubsync
Calls sync() of the most derived class
The only difference is where the functions are defined: sync is inherited from istream while flush is inherited from ostream (and fstream inherits from both). And of course the return values are different: sync returns an int (0 for ok, -1 for failure) while flush returns a reference to the stream object. But you likely don't care about those anyway.
The naming difference for input and output streams is that for input it "synchronizes" the internal buffer with the input stream (here a file) in case that changed or "flushes" pending changes from the internal buffer to the output stream (again: here a file). I.e. "sync from" and "flush to" made more sense naming wise. But for an iostream
And for completeness (almost) from Emilios answer:
std::endl, when applied to thestream with <<, is no more than a
thestream.put('\n').flush();
So it appends a newline and then calls the streams flush function which then eventually calls the buffers sync function (through pubsync).
Just a shortcut to basically use line buffering, i.e. write (up to) the end of that newline, then flush what was written.

How do I ensure data is written to disk before closing fstream?

The following looks sensible, but I've heard that the data could theoretically still be in a buffer rather than on the disk, even after the close() call.
#include <fstream>
int main()
{
ofstream fsi("test.txt");
fsi << "Hello World";
fsi.flush();
fsi.close();
return 0;
}
You cannot to this with standard tools and have to rely on OS facilities.
For POSIX fsync should be what you need. As there is no way to a get C file descriptor from a standard stream you would have to resort to C streams in your whole application or just open the file for flushing do disk. Alternatively there is sync but this flushes all buffers, which your users and other applications are going to hate.
You could guarantee the data from the buffer is written to disk by flushing the stream. That could be done by calling its flush() member function, the flush manipulator, the endl manipulator.
However, there is no need to do so in your case since close guarantees that any pending output sequence is written to the physical file.
§ 27.9.1.4 / 6:
basic_filebuf< charT, traits >* close();
Effects: If is_open() == false, returns a null pointer. If a put area exists, calls overflow(traits::eof()) to flush characters. (...)
§ 27.9.1.4
basic_filebuf* close();
Effects: If is_open() == false, returns a null pointer. If a put area
exists, calls overflow(traits::eof()) to flush characters. If the last
virtual member function called on *this (between underflow, overflow,
seekoff, and seekpos) was overflow then calls a_codecvt.unshift
(possibly several times) to determine a termination sequence, inserts
those characters and calls overflow(traits::eof()) again. Finally,
regardless of whether any of the preceding calls fails or throws an
exception, the function closes the file (as if by calling
std::fclose(file)). If any of the calls made by the function,
including std::fclose, fails, close fails by returning a null pointer.
If one of these calls throws an exception, the exception is caught and
rethrown after closing the file.
It's guaranteed to flush the file. However, note that the OS might keep it cached, and the OS might not flush it immmediately.
Which operating system are you using?
You need to use Direct (non-buffered) I/O to guarantee the data is written directly to the physical device without hitting the filesystem write-cache. Be aware it still has to pass thru the disk cache before getting physically written.
On Windows, you can use the FILE_FLAG_WRITE_THROUGH flag when opening the file.
The close() member function closes the underlying OS file descriptor. At that point, the file should be on disk.
I'm pretty sure the whole point of calling close() is to flush the buffer. This site agrees. Although depending on your file system and mount settings, just because you've 'written to the disk' doesn't mean that your file system drivers and disk hardware have actually taken the data and made magnet-y bits on the physical piece of metal. It could probably be in a disk buffer still.
How abt flushing before closing?

It's possible to write data of an unopened C++ ofstream to a file?

With unopened I mean:
ofstream outFile;
outFile << "Some text";
So I put text in an ofstream without call the .open() method. g++ does not complain, so maybe I still can save the data? How?
The stream will be in a failure state after you do this (outFile.fail() will be true). The text isn't stored anywhere, so no, you can't save it.
If you want to store data in memory, use an std::ostringstream (from the <sstream> header) instead.
g++ doesn't complain since it is a compiler and doesn't run the code, but running it may cause something nasty.
In the same way, g++ wouldn't complain if you attempt to dereference a NULL pointer.
When an action with a stream fails, the stream's stores the error internally as bits representing eof, fail and bad. The stream can also throw an exception if you set it to with ios::exceptions().
Part of the design of the iostream library seems to be that using a stream that's in an error state will silently discard output and/or produce no input, but not otherwise alert the user. The benefit of this is that you can perform multiple operations using the stream and then check it at the end, confident that if it failed somewhere in the middle it's still in a failed state and didn't produce anything since it failed.

Query regarding overflow function of streambuf

Going thorugh overflow function documentation. I found overflow has following as return values.
Return Value:
A value different than EOF (or traits::eof() for other traits) signals success.
If the function fails, either EOF (or traits::eof() for other traits) is returned or an exception is thrown.
source :"http://www.cplusplus.com/reference/iostream/streambuf/overflow/"
Can anyone please tell me in which sceanrios is overflow function going to through an exception?
Any help will be appreciated
Streambuf is abstraction for stream's underlying storage or communication channel. The overflow() function can fail for any reasons the storage or channel can fail. E.g. disk error for disk files, broken connection for sockets etc.
Although wilx detailed the fail (EOF) condition, the exception condition can be either one of these: http://www.aoc.nrao.edu/php/tjuerges/ALMA/STL/html-3.4.6/classstd_1_1exception.html (can you guess which one? :) -- but it should (obviously) be std::overflow_error if you're writing your own output stream or something.
In my problematic scenario it was faling because it was not jumping the next address(setp calls was incrementating by 0) so retrying to use the same memory region and was giving segmentation fault.

Safely overloading stream operator>>

There's a ton of information available on overloading operator<< to mimic a toString()-style method that converts a complex object to a string. I'm interested in also implementing the inverse, operator>> to deserialize a string into an object.
By inspecting the STL source, I've gathered that:
istream &operator>>(istream &, Object &);
would be the correct function signature for deserializing an object of type Object. Unfortunately, I have been at a loss for how to properly implement this - specifically how to handle errors:
How to indicate invalid data in the stream? Throw an exception?
What state should the stream be in if there is malformed data in the stream?
Should any flags be reset before returning the reference for operator chaining?
How to indicate invalid data in the stream? Throw an exception?
You should set the fail bit. If the user of the stream wants exception to be thrown, he can configure the stream (using istream::exceptions), and the stream will throw accordingly. I would do it like this, then
stream.setstate(ios_base::failbit);
What state should the stream be in if there is malformed data in the stream?
For malformed data that doesn't fit the format you want to read, you usually should set the fail bit. For internal stream specific errors, the bad bit is used (such as, if there is no buffer connected to the stream).
Should any flags be reset before returning the reference for operator chaining?
I haven't heard of such a thing.
For checking whether the stream is in a good state, you can use the istream::sentry class. Create an object of it, passing the stream and true (to tell it not to skip whitespace immediately). The sentry will evaluate to false if the eof, fail or bad bit is set.
istream::sentry s(stream, true);
if(!s) return stream;
// now, go on extracting data...
Some additional notes:
when implementing the operator>>, you probably should consider using the
bufstream and not other overloads of operator>>;
exceptions occuring during the operation should be translated to the
failbit or the badbit (members of streambuf may throw, depending on the
class used);
setting the state may throw; if you set the state after catching an
exception, you should propagate the original exception and not the one
throwed by setstate;
the width is a field to which you should pay attention. If you are
taking it into account, you should reset it to 0. If you are using other
operator>> to do basic works, you have to compute the width you are passing
from the one you received;
consider taking the locale into account.
Lange and Kreft (Standard C++ IOStreams and Locales) conver this in even
more details. They give a template code for the error handling which takes
about one page.
As for flags, I don't know if there is any standard somewhere, but it is a good idea to reset them.
Boost has neat raii wrappers for that: IO State Savers