the code as follows:
int main(int argc, char **argv)
{
const char *file = "/tmp/out";
int fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
int stdout_tmp = dup(1);
close(1);
dup(fd);
puts("hello world!");
// fflush(stdout);
close(1);
close(fd);
dup(stdout_tmp);
puts("redirect completed!");
exit(0);
}
I compile the code succssfully without any warning using gcc10.2.0, Againest my expectation, the two line both are output to the stdout instead "hello world" in the /tmp/out file and "redirect completed!" in stdout. When uncomment the fflush(stdout), it works!
I guess that the puts() doesn't refresh the buffer in user space, after restoring the stdout and exit, the buffer is auto refreshed.
gets() output string with trailing '\n' and the stdout buffer will be auto refreshed when encounter '\n'. Why need to call fflush(stdout) manually?
man 3 setvbuf
says:Since
puts()
usesstdout
we should expect a flush (because of the\n
).However, since in your example
stdout
has not been used before the redirection, I guess that the buffering behaviour is not chosen yet. At your first write attempt tostdout
, the underlying file descriptor is not a terminal anymore but a regular file. I guess the buffering behaviour is chosen at this moment.If you add another call to
puts()
in your example before the redirection, then the buffering behaviour is chosen for the terminal and then does not change afterwards when the redirection is performed. In this case, your example works as you expect (without the explicitfflush()
).edit
Still in
man 3 setvbuf
:and further:
On linux, this is consistent with your example.
In the MSDN page for
setvbuf
: