56

I have a simple program:

int main()
{
    std::cout << " Hello World";
    fork();
}

After the program executes my output is: Hello World Hello World. Why does this happen instead of a single Hello world? I'm guessing that the child process is rerun behind the scenes and the output buffer is shared between the processes or something along those lines, but is that the case or is something else happening?

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
Eumcoz
  • 2,388
  • 1
  • 21
  • 44
  • 2
    This is what fork does it spawns the process with the memory of the parent. http://linux.die.net/man/2/fork – v01d Feb 20 '12 at 16:18
  • 2
    There sure have been a lot of `fork()` questions lately... hmm... – Mysticial Feb 20 '12 at 18:42
  • hm.. Child process start execute code of program after calling of fork. So the child process just cannot cannot execute code which are above fork. – Tebe Feb 23 '12 at 16:29
  • I don't think interviews. I think a OS class. See latest refactormycode.com: http://refactormycode.com/codes/2011-linux-shell – Ants Mar 15 '12 at 08:40

8 Answers8

94

This isn't quite what you thought originally. The output buffer is not shared - when you execute the fork, both processes get a copy of the same buffer. So, after you fork, both processes eventually flush the buffer and print the contents to screen separately.

This only happens because cout is buffered IO. If you used cerr, which is not buffered, you should only see the message one time, pre-fork.

John Humphreys
  • 37,047
  • 37
  • 155
  • 255
44

standard output uses buffered IO. When the fork() is called the standard output is not flushed and the buffered content is replicated in the child process. These buffers are flushed when the process exit, resulting in the two outputs that you see.

If you change the program to:

std::cout << " Hello World;" << std::endl;

you should see only one.

hmjd
  • 120,187
  • 20
  • 207
  • 252
17

Because you called fork() without flushing all buffers first.

cout.flush();
fork();
Joshua
  • 40,822
  • 8
  • 72
  • 132
10

The code to output "Hello World" is only executed once. The issue is that the output buffer isn't flushed. So when you fork the process, "Hello World" is still sitting in the output buffer. When both programs exit, their output buffers will be flushed and you'll see the output twice.

The easiest way to demonstrate this is by adding a newline at the end of your string, which will cause an implicit flush, or explicitly flush with std::cout.flush();. Then you'll only see the output once.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
Michael Mior
  • 28,107
  • 9
  • 89
  • 113
9

If you use:

std::cout << " Hello World" << std::flush;

You only see one. I guess fork() copies whatever output buffer std::cout writes to.

James M
  • 18,506
  • 3
  • 48
  • 56
6

The string is not immediately written to the screen; instead, it's written to an internal buffer. The child process inherits a copy of the output buffer, so when the child's cout is automatically flushed, Hello World is printed to the screen. The parent also prints Hello World.

If you flush cout before the fork(), the problem will almost certainly go away.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
3

The reason is that the when you invoke std::cout<< it doesn't really perform the output itself but data is left in a buffer in the system. When you do the fork, both code and data are copied, as well as all the buffers associated. Finally, both father and son flush them to the standard output and thus you see the output duplicated.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
Genís
  • 1,468
  • 2
  • 13
  • 24
2

What you're likely seeing here is an effect of buffering. In general output is buffered until it's explicitly flushed or implicitly done with an action like outputting a new line. Because the output is buffered both copies of the forked process have bufferred output and hence both display it upon the process terminating and flushing the buffer

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454