toothie
toothie

Reputation: 1029

Working of fork() in C++

I have this program in C++.

#include <iostream>
#include <unistd.h>
#include  <sys/types.h>


using namespace std;

int main()
{
    cout<<"*\n";
    fork();
    cout<<"A\n";
    fork();
    cout<<"B\n";
    fork();
    cout<<"C\n";
    return 0;
}

The output is:

*
A
B
C
*
A
B
C

I think it should be:

*
A
B
C
A
B
C
B
C
C

Explanation: '*' should be printed on by one process. Now, after fork() 2 'A' should be printed and son for 'B' & 'C'.

Link to code

Upvotes: 4

Views: 1337

Answers (2)

TBBle
TBBle

Reputation: 1476

Based on comments on the question, the answer is that fork in the ideone.com online compiler is simply limiting you to one instance of your process, and buffering your output.

Update: Actually, it's also lying: http://ideone.com/oXqqwM shows that fork() claims to succeed, but only the first produces a new copy of your process.

I suspect if you checked the return values of fork() you'd get some clues as to the surprising behaviour you're seeing -- all but the first will have returned -1 -- and if you used std::endl instead you might avoid the first *.

The expected result is that each fork() duplicates the running process at that moment, and so you'd expect to see twice each character compared to the one before, except that buffering means you might still have previous characters in the buffer at the time of fork().

So expect 1 or more "*", 2 or more "A", 4 or more "B" or 8 or more "C", except that if fork() fails, the numbers will be capped.

Your expectation of 1 "*", 2 "A", 3 "B" and 4 "C" indicates that you overlooked that both processes coming out of a fork() will hit the next fork(), so you double, rather than incrementing by one.

Upvotes: 1

Grady Player
Grady Player

Reputation: 14549

so... if you are getting more than one * then there is something strange going on, and I suspect that it is implementation specific... fork will give each of the child processes a copy of the file descriptors, including stdout... so in your implementation it is also getting a valid copy of the std::cout stream... which already has a buffer loaded with *...

I think if you change your program to include a flush, you will see the same thing that I did:

#include <iostream>
#include <unistd.h>
#include  <sys/types.h>


using namespace std;

int main()
{
    cout<< "*\n";
    flush(cout);
    fork();
    cout<<"A\n";
    flush(cout);
    fork();
    cout<<"B\n";
    flush(cout);
    fork();
    cout<<"C\n";
    flush(cout);
    return 0;
}

Upvotes: 0

Related Questions