I know there are many buffer questions on here but I can't seem find a clear answer on this.
std::cout << "write to screen" << std::endl;
I know this code will write to the screen and flush the buffer because of the "endl", but if I wrote this:
std::cout << "write to screen";
Wouldn't the buffer be flushed regardless since the text has been outputted to the screen?
Wouldn't the buffer be flushed regardless since the text has been outputted to the screen?
Assuming that you have seen the text outputted to the screen, then yes, the buffer has been flushed.
I believe the confusion is regarding this line:
std::cout << "write to screen";
The absence of std::endl doesn't mean "don't flush the buffer". It simply means "I'm not saying when to flush the buffer".
There are multiple ways to ensure your std::ostream is flushed:
Manually with std::endl, std::flush, or a direct call to ostream::flush().
Depending on a later used input stream being bound to your ostream: std::basic_ios::tie().
Depending on the tie to C streams: std::ios_base::sync_with_stdio
This means that anything which would flush the corresponding C stream will also flush the C++ stream, like a call to fflush(), or the (maybe automatically) selected buffering strategy.
Like line-buffering.
From C11 draft:
7.21.3 Files
3 When a stream is unbuffered, characters are intended to appear from the source or at the
destination as soon as possible. Otherwise characters may be accumulated and
transmitted to or from the host environment as a block. When a stream is fully buffered,
characters are intended to be transmitted to or from the host environment as a block when
a buffer is filled. When a stream is line buffered, characters are intended to be
transmitted to or from the host environment as a block when a new-line character is
encountered. Furthermore, characters are intended to be transmitted as a block to the host
environment when a buffer is filled, when input is requested on an unbuffered stream, or
when input is requested on a line buffered stream that requires the transmission of
characters from the host environment. Support for these characteristics is
implementation-defined, and may be affected via the setbuf and setvbuf functions.
7 At program startup, three text streams are predefined and need not be opened explicitly
— standard input (for reading conventional input), standard output (for writing
conventional output), and standard error (for writing diagnostic output). As initially
opened, the standard error stream is not fully buffered; the standard input and standard
output streams are fully buffered if and only if the stream can be determined not to refer
to an interactive device.
Waiting on the internal buffer overflowing.
Now, as a general guideline: Don't manually flush your streams, doing so can significantly degrade performance. Unless, of course, it's neccessary for correctness.
std::cout << "Hello" << std::endl;
will write to the screen before executing the next line of code, while
std::cout << "Hello\n";
will print the same, but some time before your program exits normally or you use std::cin (or another instream you tie to std::cout by hand). That means that if your program is terminated abruptly or hangs in an infinite loop, you might not see the output at all.
"Wouldn't the buffer be flushed regardless since the text has been outputted to the screen?"
No! std::endl implies flushing. The underlying buffer won't be flushing (written on the screen),
until hitting a certain watermark (buffer size).
If you want to have it flushed, call cout.flush() explicitely:
std::cout << "write to screen";
std::cout.flush();
The real key to the solution is, what the underlying std::basic_streambuf interface actually implements.
There could be various implementations:
Calling flush() every time the certain watermark of the underlying buffer is hit
Calling flush() every time (not very efficient)
Calling flush() as soon a '\n' had been printed
Calling flush() as guaranteed with std::endl
The internal buffer management shouldn't be your business of concern, unless you're trying to provide your own std::basic_streambuf implementation.
Related
According to the definition of endl, it is used to insert a new-line character and flush the stream. And I remember that if a new line is inserted, then the buffer will be flushed automatically. If so, why do endl still need to flushes the stream after inserting a new line.
if a new line is inserted, then the buffer will be flushed automatically
Not necessarily, and not for all streams. It's common for std::cout (and the standard output stream it sends data to) to be line-buffered, but not universal. Some implementations, for example, only line-buffer stdout if output is going to a terminal, and fully-buffer it otherwise (if output is redirected to a pipe, for example).
And that's just for standard output. Other streams like file I/O are almost always fully-buffered and the buffer will only be flushed when it either fills up or its flushed explicitly.
In case of buffered stream it said in a book that it wait until the buffer is full to write back to the monitor. For example:
cout << "hi";
What do they mean by "the buffer is full".
cerr << "hi";
It is said in my book that everything sent to cerr is written to the standard error device immediately, what does it mean?
char *ch;
cin>> ch; // I typed "hello world";
In this example ch will be assigned to "hello" and "world" will be ignored does it mean that it still in the buffer and it will affect the results of future statements?
Your book doesn't seem very helpful.
1) The output streams send their bytes to a std::streambuf, which may
contain a buffer; the std::filebuf (derived from streambuf) used by
and std::ofstream will generally be buffered. That means that when
you output a character, it isn't necessarily output immediately; it will
be written to a buffer, and output to the OS only when the buffer is
full, or you explicitly request it in some way, generally by calling
flush() on the stream (directly, or indirectly, by using std::endl).
This can vary, however; output to std::cout is synchronized with
stdout, and most implementations will more or less follow the rules of
stdout for std::cout, changing the buffering strategy if the output
is going to an interactive device.
At any rate, if you're unsure, and you want to be sure that the output
really does leave your program, just add a call to flush.
2) Your book is wrong here.
One of the buffering strategies is unitbuf; this is a flag in the
std::ostream which you can set or reset (std::ios_base::set() and
std::ios_base::unset()—std::ios_base is a base class of
std::ostream, so you can call these functions on an std::ostream
object). When unitbuf is set, std::ostream adds a call to flush()
to the end of every output function, so when you write:
std::cerr << "hello, world";
the stream will be flushed after all of the characters in the string
are output, provided unitbuf is set. On start-up, unitbuf is set
for std::cerr; by default, it is not set on any other file. But you
are free to set or unset it as you wish. I would recommend against
unsetting it on std::cerr, but if std::cout is outputting to an
interactive device, it makes a lot of sense to set it there.
Note that all that is in question here is the buffer in the streambuf.
Typically, the OS also buffers. All flushing the buffer does is
transfer the characters to the OS; this fact means that you cannot use
ofstream directly when transactional integrity is required.
3) When you input to a string or a character buffer using >>, the
std::istream first skips leading white space, and then inputs up to
but not including the next white space. In the formal terms of the
standard, it "extracts" the characters from the stream, so that they
will not be seen again (unless you seek, if the stream supports it).
The next input will pickup where ever the previous left off. Whether
the following characters are in a buffer, or still on disk, is really
irrelevant.
Note that the buffering of input is somewhat complex, in that it occurs
at several different levels, and at the OS level, it takes different
forms depending on the device. Typically, the OS will buffer a file by
sectors, often reading several sectors in advance. The OS will always
return as many characters as were demanded, unless it encounters end of
file. Most OSs will buffer a keyboard by line: not returning from a
read request until a complete line has been entered, and never returning
characters beyond the end of the current line in a read request.
In the same manner as std::ostream uses a streambuf for output,
std::istream uses one to get each individual character. In the case
of std::cin, it will normally be a filebuf; when the istream
requests a character, the filebuf will return one from its buffer if
it has one; if it doesn't, it will attempt to refill the buffer,
requesting e.g. 512 (or whatever its buffer size is) characters from the
OS. Which will respond according to its buffering policy for the
device, as described above.
At any rate, if std::cin is connected to the keyboard, and you've
typed "hello world", all of the characters you've typed will be read
by the stream eventually. (But if you're using >>, there'll be a lot
of whitespace that you won't see.)
streams in C++ are buffer to increase efficiency, that is file and console IO is very slow in comparison to memory operations.
To combat this C++ streams have a buffer (a bank of memory) that contains everything to write to the file or output, when it is full then it flushed to the file. The inverse is true for input, it fetches more when it the buffer is depleted.
This is very import for streams because the following
std::cout << 1 << "hello" << ' ' << "world\n";
Would be 4 writes to a file which is inefficient.
However in the case of std::cout, cin, and cerr then these type actually have buffering turned off by default to ensure that it can be used in conjunction with std::printf and std::puts etc...
To re-enable it (which I recommend doing):
std::ios_base::sync_with_stdio(false);
But don't use C style console output whilst it is set false or bad things may happen.
You can check out the differences yourself with a small app.
#include <iostream>
int main() {
std::cout<<"Start";
//std::cout<<"Start"<<std::endl; // line buffered, endl will flush.
double j = 2;
for(int i = 0; i < 100000000; i++){
j = i / (i+1);
}
std::cout<<j;
return 0;
}
Try out the difference of the two "Start" statments, then change to cerr. The difference you notice is due to buffering.
The for-statement takes about 2 seconds on my rig, you might need to tweak the i < condition on yours.
1) what do they mean by "the buffer is full".
With buffered output there's a region of memory, called a buffer, where the stuff you write out is stored before it is actually written to the output. When you say cout << "hi" the string is probably only copied into that buffer and not written out. cout usually waits until that memory has been filled up before it actually starts writing things out.
The reason for this is because usually the process of starting to actually write data is slow, and so if you do that for every character you get terrible performance. A buffer is used so that the program only has to do that infrequently and you get much better performance.
2) it said in my book that everything sent to cerr is written to the standard error device immediatly, does this mean it send 'h' and then 'i'...?
It just means that no buffer is used. cerr might still send 'h' and 'i' at the same time since it already has both of them.
3)in this example ch will be assigned to "hello" and "world" will be ignored does it mean that it still in the buffer and it will affect the results of future statements ?
This doesn't really have anything to do with buffering. the operator >> for char* is defined to read until it sees whitespace, so it stops at the space between "hello" and "world". But yes, the next time you read you will get "world".
(although if that code isn't just a paraphrase of the actuall code then it has undefined behavior because you're reading the text into an undefined memory location. Instead you should do:
std::string s;
cin >> s;
)
Each call to write to the terminal is slow, so to avoid doing slow things often the data is stored in memory until either a certain amount of data has been entered or the buffer is flushed manually with fflush or std::endl. The result of this is sometimes that text might not be written to the terminal at the moment you expect it to.
Since the timing of error messages is more critical than normal output, the performance hit is ignored and the data is not buffered. However, since a string is passed in a single piece of data, it is written in one call (inside a loop somewhere).
It world would still be in the buffer, but it's quite easy to prove this yourself by trying it in a 3 line program. However, your example will fail since you are attempting to write into unallocated memory. You should be taking input into a std::string instead.
EDITED
Input stream and Input buffer
From what I understand, when a key is pressed on the keyboard, the character go into the input stream (stdin) and get stored in the buffer. Then the scanf (in case of C) or cin(in case of C++) extracts the character from the buffer and places it in the main memory.
Output stream and Output buffer
Similarly, before characters are displayed on the screen, they are first stored in a buffer. Then the printf (in case of C) or cout(in case of C++) extracts the characters from the buffer (when it is full) and sends it to the output (stdout) stream.
Am I right? I've been stuck on this for quite a while now and my logic may be flawed.
Side note: scanf() is not the function to read input, see more here.
Now for your question: When asking about C (and, C++), e.g., the language, you should stay within the abstract concepts the language provides. So, don't start at the keyboard, that's far outside your program.
Start here: The operating system wants to deliver some input to you. Now, your C runtime provides a stream of input to your code. The stream is an abstract concept, it just means something you can continuously read from. This stream can be buffered or unbuffered, and if it's buffered, there are different modes (fully buffered or line buffered) available. You can configure all of that.
If your stream is unbuffered, this means the operating system has to wait until your code wants to read from the input stream. By default, your standard input stream is line buffered, which means your C runtime accepts the input immediately and puts it into a buffer until there is a newline -- your code calling input functions will get a result from that buffer.
Conceptually the same happens with output, just the other way around. If your output stream is for example line buffered, your C runtime will fill a buffer until there is a newline and deliver that whole line to the operating system for output. If the output is unbuffered, every single character is immediately passed to the operating system.
Disclaimer: this is still a lot simplified, but should be enough to start with.
As you ask about the term "buffer overflow" in the comments, mentioning gets() -- this is about a buffer inside your own code. With any input function that reads more than a single value/char, you have to provide your own buffer for it to store the result to. With gets(), there's no way to tell the function how large this buffer is, so it will just overflow it whenever the input available is too large. This is why gets() is ill-defined and meanwhile removed from the language C. It has nothing to do with buffers of your C runtime that are possibly used in the implementation of the I/O streams.
Can someone please explain (preferably using plain english) how std::flush works?
What is it?
When would you flush a stream?
Why is it important?
Thank you.
Since it wasn't answered what std::flush happens to be, here is some detail on what it actually is. std::flush is a manipulator, i.e., a function with a specific signature. To start off simple, you can think of std::flush of having the signature
std::ostream& std::flush(std::ostream&);
The reality is a bit more complex, though (if you are interested, it is explained below as well).
The stream class overload output operators taking operators of this form, i.e., there is a member function taking a manipulator as argument. The output operator calls the manipulator with the object itself:
std::ostream& std::ostream::operator<< (std::ostream& (*manip)(std::ostream&)) {
(*manip)(*this);
return *this;
}
That is, when you "output" std::flush with to an std::ostream, it just calls the corresponding function, i.e., the following two statements are equivalent:
std::cout << std::flush;
std::flush(std::cout);
Now, std::flush() itself is fairly simple: All it does is to call std::ostream::flush(), i.e., you can envision its implementation to look something like this:
std::ostream& std::flush(std::ostream& out) {
out.flush();
return out;
}
The std::ostream::flush() function technically calls std::streambuf::pubsync() on the stream buffer (if any) which is associated with the stream: The stream buffer is responsible for buffering characters and sending characters to the external destination when the used buffer would overflow or when the internal representation should be synced with the external destination, i.e., when the data is to be flushed. On a sequential stream syncing with the external destination just means that any buffered characters are immediately sent. That is, using std::flush causes the stream buffer to flush its output buffer. For example, when data is written to a console flushing causes the characters to appear at this point on the console.
This may raise the question: Why aren't characters immediately written? The simple answer is that writing characters is generally fairly slow. However, the amount of time it takes to write a reasonable amount of characters is essentially identical to writing just one where. The amount of characters depends on many characteristics of the operating system, file systems, etc. but often up to something like 4k characters are written in about the same time as just one character. Thus, buffering characters up before sending them using a buffer depending on the details of the external destination can be a huge performance improvement.
The above should answer two of your three questions. The remaining question is: When would you flush a stream? The answer is: When the characters should be written to the external destination! This may be at the end of writing a file (closing a file implicitly flushes the buffer, though) or immediately before asking for user input (note that std::cout is automatically flushed when reading from std::cin as std::cout is std::istream::tie()'d to std::cin). Although there may be a few occasions where you explicitly want to flush a stream, I find them to be fairly rare.
Finally, I promised to give a full picture of what std::flush actually is: The streams are class templates capable of dealing with different character types (in practice they work with char and wchar_t; making them work with another characters is quite involved although doable if you are really determined). To be able to use std::flush with all instantiations of streams, it happens to be a function template with a signature like this:
template <typename cT, typename Traits>
std::basic_ostream<cT, Traits>& std::flush(std::basic_ostream<cT, Traits>&);
When using std::flush immediately with an instantiation of std::basic_ostream it doesn't really matter: The compiler deduces the template arguments automatically. However, in cases where this function isn't mentioned together with something facilitating the template argument deduction, the compiler will fail to deduce the template arguments.
By default, std::cout is buffered, and the actual output is only printed once the buffer is full or some other flushing situation occurs (e.g. a newline in the stream). Sometimes you want to make sure that the printing happens immediately, and you need to flush manually.
For example, suppose you want to report a progress report by printing a single dot:
for (;;)
{
perform_expensive_operation();
std::cout << '.';
std::flush(std::cout);
}
Without the flushing, you wouldn't see the output for a very long time.
Note that std::endl inserts a newline into a stream as well as causing it to flush. Since flushing is mildly expensive, std::endl shouldn't be used excessively if the flushing isn't expressly desired.
Here's a short program that you can write to observe what flush is doing
#include <iostream>
#include <unistd.h>
using namespace std;
int main() {
cout << "Line 1..." << flush;
usleep(500000);
cout << "\nLine 2" << endl;
cout << "Line 3" << endl ;
return 0;
}
Run this program: you'll notice that it prints line 1, pauses, then prints line 2 and 3. Now remove the flush call and run the program again- you'll notice that the program pauses and then prints all 3 lines at the same time. The first line is buffered before the program pauses, but because the buffer is never flushed, line 1 is not outputted until the endl call from line 2.
A stream is connected to something. In the case of standard output, it could be the console/screen or it could be redirected to a pipe or a file. There is a lot of code between your program and, for example, the hard disk where the file is stored. For example, the operating system is doing stuff with any file or the disk drive itself might be buffering data to be able to write it in fixed size blocks or just to be more efficient.
When you flush the stream, it tells the language libraries, the os and the hardware that you want to any characters that you have output so far to be forced all the way to storage. Theoretically, after a 'flush', you could kick the cord out of the wall and those characters would still be safely stored.
I should mention that the people writing the os drivers or the people designing the disk drive might are free to use 'flush' as a suggestion and they might not really write the characters out. Even when the output is closed, they might wait a while to save them. (Remember that the os does all sorts of things at once and it might be more efficient to wait a second or two to handle your bytes.)
So a flush is a sort of checkpoint.
One more example: If the output is going to the console display, a flush will make sure the characters actually get all the way out to where the user can see them. This is an important thing to do when you are expecting keyboard input. If you think you have written a question to the console and its still stuck in some internal buffer somewhere, the user doesn't know what to type in answer. So, this is a case where the flush is important.
I am new to C++ learning from C++ Primer book. In the first chapter, writer talks about the buffer of the iostream, cout, and endl. I could not understand well. I have two example codes here.
#include<iostream>
int v1;
int main()
{
std::cout<<"First Cout!";
std::cin>>v1;
std::cout<<"Second Cout!"<<std::endl;
std::cout<<"Third Cout!\n";
return 0;
}
I want to know the state of the cout buffer after execution of each line.
The stream contains an in-memory buffer where data is written before being flushed to the final destination (in this case, the output console), since flushing can be an expensive operation.
The buffer might be flushed automatically in some circumstances: when the stream is closed, or if there's a lot of buffered data, or if the stream is configured to flush after each line, as std::cerr is.
Sometimes you need to flush manually, for example to make sure the user sees something you've written to std::cout. That can be done in two ways:
calling the flush() member function on the stream;
streaming the std::flush manipulator into the stream.
The std::endl manipulator does two things:
inserts a new-line character (or character sequence), equivalent to << '\n'; then
flushes the stream, equivalent to << std::flush, (which is in turn calls the stream's flush() member function).
This is useful for writing short messages to the console; but should be used carefully, as it can have a considerable performance impact when producing large amounts of output.
A further complication is that one stream can be tied to another, so that one is flushed before another is accessed. In this case, cout is tied to cin, which is why you see the first output before reading from cin even though there is no explicit flush.
Finally, all the standard streams, including cout, are flushed automatically when the program ends (specifically, when the global instance of std::ios_base::Init is destroyed; but that's a detail you shouldn't need to know about.)
After first line, the output is in the buffer, so you will not see it in the terminal.
After the second line, the endl causes the buffer to be flushed so you will now see line 1 and 2 in the terminal output.
After the third line, output is in the buffer and you will not see it in the terminal until the program exits.
Edit:
When you place a cin between line 1 and 2, it causes cout to be flushed. See: std::cin
cin is tied to the standard output stream cout (see ios::tie), which indicates that cout's buffer is flushed (see ostream::flush) before each i/o operation performed on cin.
After 1st line, cout contains just the given string with no newline char.
After 2nd line, cout additionally contains a line ending and the text appears at the console window.
After 3rd line, cout contains another string including line ending which not necessarily appears at the console window.
After exiting main, the text of the 3rd line is appears.
std::endl just adds EOL (end of line) symbol to output. Usually its \n, but it can vary from one OS to another.