Reputation: 729
I have this tiny program in C
main(int argc, char **argv)
{
forkit(4);
}
void forkit(int n)
{
if(n > 0)
{
fork();
printf("%d \n", n);
forkit(n-1);
}
}
which prints
4 4 3 3 3 3 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
30 numbers, all in new lines. However, if I remove the \n
in the printf
statement it prints this:
4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1
Without new line it gives 64 numbers.
How is such a small change giving such different results?
Upvotes: 3
Views: 120
Reputation: 146221
Very good question, there is something subtle going on.
What's happening is that printf's output is line buffered and flushed at newlines.
All by itself, that doesn't affect the output of most programs, just the speed.
But when you fork, buffered I/O that hasn't yet been output is now present in both children. With the newline in that output has already happened so it is no longer pending in the child.
That's the explanation. If it isn't clear, another way to phrase it is: without the newline, the pending output is multiplied by the number of future children in the process tree. With the newline, it's just output that happened in the past and the program works like you expect it to.
Note that the output eventually gets flushed even without the newline, but it happens when the program calls exit(3).
By then, it has already forked and passed on it's pending (i.e., buffered) output.
By the way, if you redirect the output to a file, it will be block buffered and you will probably see similar results (except for the newlines) in both cases.
Upvotes: 7