Тут важливим є той факт, що stdout
для встановлення за замовчуванням необхідна лінія, яка буде забудована стандартом.
Це призводить \n
до змивання виводу.
Оскільки другий приклад не містить нового рядка, вихід не розмивається і, як fork()
копіює весь процес, він також копіює стан stdout
буфера.
Тепер ці fork()
виклики у вашому прикладі створюють загалом 8 процесів - усі вони мають копію стану stdout
буфера.
За визначенням, всі ці процеси викликають exit()
при поверненні з main()
та exit()
виклики, fflush()
за якими слідують fclose()
усі активні потоки stdio . Це включає stdout
і, як результат, ви бачите один і той же вміст вісім разів.
Доцільно зателефонувати fflush()
в усі потоки з очікуванням виходу перед викликом fork()
або дозволити виклику дочірнього дзвінка чітко _exit()
виходити з процесу лише без змивання потоків stdio.
Зауважте, що виклик exec()
не змиває буфери stdio, тому добре, щоб ви не піклувалися про буфери stdio, якщо ви (після виклику fork()
) дзвоните exec()
та (якщо це не вдається) дзвонити _exit()
.
BTW: Щоб зрозуміти, що неправильне буферизація може спричинити, ось колишня помилка в Linux, яку нещодавно виправили:
Стандарт вимагає stderr
розблокувати за замовчуванням, але Linux проігнорував це і зробив stderr
буферизовану лінію та (ще гірше) повністю буферизовану у випадку, якщо stderr був перенаправлений через трубу. Тому програми, написані для UNIX, надто пізно виводили матеріали без нового рядка в Linux.
Дивіться коментар нижче, здається, виправлено зараз.
Це те, що я роблю, щоб вирішити цю проблему Linux:
/*
* Linux comes with a broken libc that makes "stderr" buffered even
* though POSIX requires "stderr" to be never "fully buffered".
* As a result, we would get garbled output once our fork()d child
* calls exit(). We work around the Linux bug by calling fflush()
* before fork()ing.
*/
fflush(stderr);
Цей код не шкодить на інших платформах, оскільки виклик fflush()
потоку, щойно розмитого, є noop.
./prog1 > prog1.out
) або трубу (./prog1 | cat
). Підготуйтеся, щоб ваш розум був роздутий. :-)