It is an academic question so the reason is to understand the output.
I have a code:
int main(int argc, char **argv) {
int k ;
while(*(++argv)) {
k = fork();
printf("%s ",*argv);
}
return 0;
}
running the program with : prog a b
The output is :
a b a b a b a b
Why do I get this result?
First things first, terminal is line buffered, i.e, buffers are flushed when newline is encountered. If you put a newline in printf() than results would change. However, if you are writing to a file, which is fully buffered, there will be no change in the output even if you add the newline to printf().
After the first fork() call, P (parent) has 'a' and C1 also has 'a'. (C for child).
Then, after the second fork call, two new children are created C2 and C3. The buffers of the process are also copied, so C2 and C3 also contains 'a' now. After the printf() call, all the processes contain 'a b' in their buffers. And when they exit, their buffers are flushed, and hence the output.
I don't know about "fork", but I can tell you that on the second iteration of the loop you are accessing a meaningless area of memory. That surely returns corrupted, meaningless results, and worse, it can break the execution of the program.
You should, of course, be doing something like
while ((--argc) >= 0) { (...) }
if you don't need to know the original value of
argc
after the loop, or elseIn the beginning
argv
will point toargv[0]
which is the executable file name, it's increased once insidewhile()
to point toargv[1]
.Now it hits
fork()
creating a second thread starting at the same line.Both threads will write
a
to their ownstdout
buffer.Now
argv
is moved by 1 character in both instances (insidewhile()
), as they essentially work with copies if I remember that correctly.The fork in each thread will now create 2 additional copies of the thread (one for each existing thread).
Now the 4 instances will all have the 'a ' still in their
stdout
buffer that is copied (think so, would be nice if anyone could confirm this) and theirargv
pointing tob
. This one is written as well, so now we've got 4 threads each having 'a b ' in their output buffers.Once they end, their buffers are flushed resulting in the 'a b a b a b a b ' (essentially being 'a b ', 'a b ', 'a b ', and 'a b ').
Ben's comment can be explained by flushing caused by the linebreaks.
As suggested by Chris Lutz in the comments, you are observing the effect of a static buffer used by
printf
being duplicated by thefork()
call. The two processes created by the firstfork()
do not printb
(as you could expect, and as happens if you force a flush). They both printa b
because they both have a pending, unflusheda
in their respective buffers.There are 4 processes (2^2, including the initial one), they all only really print at exit when the buffer is flushed, and they all have
a b
in their respective buffers at that time.