5

According to my understanding of fork(), this should print "Hello, World!" once, since there is only one process before fork is called. However, it prints twice. Curiously, if I add a \n to the string or use puts() instead of printf(), it only prints once.

#include<unistd.h>
#include<stdio.h>

int main() {
    printf("Hello, World!");
    fork();
}
Brian McCutchon
  • 8,354
  • 3
  • 33
  • 45
  • 2
    Brian, please use search before asking. Many questions already have an answer. – 2501 Mar 09 '17 at 08:40
  • @2501 I did. I probably didn't use the right terms. I also looked at the top suggestions for things that might answer my question when I was typing the question. – Brian McCutchon Mar 09 '17 at 08:45
  • Try using a third-party search engine, and narrow the search on this site. – 2501 Mar 09 '17 at 08:47
  • @2501 That's what I used. I think I didn't include `printf` as a term because I didn't realize this was a `printf` problem; I assumed everything before `fork` was being run twice. – Brian McCutchon Mar 09 '17 at 08:49
  • 1
    I think this is a much better (clearer) question than the linked duplicates, and would make a good canonical version for this issue. – Toby Speight Mar 09 '17 at 09:00

3 Answers3

5

Buffering.

Since standard output on your system is buffered by default, it doesn't print immediately. The buffer will however be flushed before the process is exited.

Since fork copies the parents entire memory space, file descriptor state, etc, it will also copy the buffered data that needs to be printed.

As such, unless you explicitly flush the standard output buffer before forking (by appending \n to the output or calling fflush(stdout);), both processes will have buffered output to print.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • @Jean-FrançoisFabre It helps when that technology has annoying gotchas like this... I just spent well over an hour trying to find the issue in my code before I narrowed it down to this. – Brian McCutchon Mar 09 '17 at 08:33
  • actually it's a duplicate. Damn. Too bad :) – Jean-François Fabre Mar 09 '17 at 08:34
  • 1
    Where is it specified that "*standard output is buffered by default*"? AIUI, the initial buffering mode is entirely up to the implementation, and the most common choice is that *[`stdin` and `stdout` are line-buffered **when associated with a terminal**, and fully-buffered otherwise](/a/3746795)*. Because of this, I advise `fflush()` over `\n`. – Toby Speight Mar 09 '17 at 08:41
  • @TobySpeight - If my statement implies I was referring to any particular standard, I wasn't (although I'm not sure how to correct it so it's clearer). It was merely an explanation of the observable behavior of this program. – StoryTeller - Unslander Monica Mar 09 '17 at 08:44
2

The explanation I can provide:

printf("Hello, World!"); doesn't print at once because output is not flushed to stdout.

when fork() copies process memory, it copies internal buffers, and when both processes terminate, both processes flush their buffers and the text is outputted twice.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
2

Output to stdout (which is where printf writes it output) is by default line buffered. That means its buffer will be be flushed (and actually written to the output) when you print a newline (or the buffer gets full).

If you don't print a newline, then the buffered output will be duplicated by the child process, and both the parent and child process will each flush its own buffer when the processes ends, leading to two outputs being printed.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • As I noted in a comment to StoryTeller's answer, `stdout` *may* be initially line-buffered, but it's up to the implementation. All you can say in this situation is that the output was buffered in that particular run of the program. The general advice (to use `fflush()` if you don't want both parent and child to write the buffered output) still stands, of course. – Toby Speight Mar 09 '17 at 08:56