There is this exceptionally simple program in C (built with gcc on Cygwin)::
// This program is a tutorial to Stack-based overflow, that's why "gets"
#include <stdio.h>
void test()
{
char buff[4];
printf("Some input: ");
gets(buff);
puts(buff);
}
int main(int argc, char** argv)
{
test();
return 0;
}
Now when I run this on Windows console,printf
executes first and waits for the input::
But when I run the same exe under Cygwin terminal, it waits for the input and then printf
executes::
Why is this difference?
EDIT:: With \n
appended to the string in printf
statement, the behaviour remains the same::
So, after some reading and research, I concluded at a final theory for this behaviour.
Short Answer:: stdout
is buffered, so doing a
void test()
{
char buff[4];
setvbuf(stdout, NULL, _IONBF, 0); // <--- setting stdout to _IONBF
printf("Some input: ");
gets(buff);
puts(buff);
}
before printing anything to console or,
void test()
{
char buff[4];
printf("Some input: ");
fflush(stdout); // <--- force the stdout to flush
gets(buff);
puts(buff);
}
after the printf
statement will solve the issue.
Long Answer::
When I run the same exe with Bash.exe
, the stdout is not buffered::
And the same exe with mintty.exe
, the stdout is buffered::
Now the question is,
stdout
is unbuffered in one and buffered on another?As you can see the
tty
output on both, bash shows as console session/dev/cons0
, whereas the mintty shows as pseudo-terminal session/dev/pty0
.
So,
My browsing re-re-and-re searches landed me here, stating, If I type
tty
in the respective Cygwin windows, I see thatmintty
andxterm
are both pseudo-terminals whereasbash
is a console session - I believeprocServ
usesforkpty()
. So I think it boils down to Windows treating a Cygwin pty as non-interactive and thus buffering bothstdout
andstderr
.
I am not sure, how precise this is but yes, this seems to be a practical and best explanation of this behaviour.
According to Section 7.9.13/7 of c99
states that:
At program start-up, 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.
*The bold emphasis is mine.