Latar belakang yang penting di sini adalah bahwa garisstdout
harus disangga oleh standar sebagai pengaturan default.
Ini menyebabkan a \n
untuk menyiram output.
Karena contoh kedua tidak mengandung baris baru, output tidak memerah dan sebagai fork()
salinan seluruh proses, itu juga menyalin keadaan stdout
buffer.
Sekarang, fork()
panggilan ini dalam contoh Anda membuat total 8 proses - semuanya dengan salinan status stdout
buffer.
Menurut definisi, semua proses ini memanggil exit()
saat kembali dari main()
dan exit()
panggilan fflush()
diikuti oleh fclose()
semua aliran stdio aktif . Ini termasuk stdout
dan sebagai hasilnya, Anda melihat konten yang sama delapan kali.
Merupakan praktik yang baik untuk memanggil fflush()
semua aliran dengan output yang tertunda sebelum memanggil fork()
atau membiarkan anak bercabang memanggil secara eksplisit _exit()
yang hanya keluar dari proses tanpa menyiram aliran stdio.
Perhatikan bahwa panggilan exec()
tidak menghilangkan buffer stdio, jadi tidak apa-apa untuk tidak peduli tentang buffer stdio jika Anda (setelah menelepon fork()
) memanggil exec()
dan (jika itu gagal) menelepon _exit()
.
BTW: Untuk memahami bahwa buffering yang salah dapat menyebabkan, berikut adalah bug di Linux yang baru-baru ini diperbaiki:
Standar ini stderr
harus di-unbuffered secara default, tetapi Linux mengabaikannya dan membuat stderr
line buffered dan (bahkan lebih buruk) sepenuhnya buffered jika stderr dialihkan melalui pipa. Jadi program yang ditulis untuk UNIX melakukan output barang tanpa baris baru terlambat di Linux.
Lihat komentar di bawah, sepertinya sudah diperbaiki sekarang.
Inilah yang saya lakukan untuk mengatasi masalah Linux ini:
/*
* 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);
Kode ini tidak membahayakan platform lain karena memanggil fflush()
stream yang baru saja dibilas adalah noop.
./prog1 > prog1.out
) atau pipa (./prog1 | cat
). Bersiaplah untuk memiliki pikiran Anda meledak. :-)