El trasfondo importante aquí es que stdout
se requiere que el estándar proteja la línea como configuración predeterminada.
Esto hace que \n
a vacíe la salida.
Como el segundo ejemplo no contiene la nueva línea, la salida no se vacía y, como fork()
copia todo el proceso, también copia el estado del stdout
búfer.
Ahora, estas fork()
llamadas en su ejemplo crean 8 procesos en total, todos ellos con una copia del estado del stdout
búfer.
Por definición, todos estos procesos llaman exit()
cuando regresan main()
y exit()
llamadas fflush()
seguidas de fclose()
todas las secuencias stdio activas . Esto incluye stdout
y, como resultado, ve el mismo contenido ocho veces.
Es una buena práctica llamar fflush()
a todas las secuencias con salida pendiente antes de llamar fork()
o dejar que la llamada secundaria bifurcada explícitamente _exit()
solo salga del proceso sin vaciar las secuencias stdio.
Tenga en cuenta que las llamadas exec()
no eliminan las memorias intermedias estándar, por lo que está bien no preocuparse por las memorias intermedias si usted (después de llamar fork()
) llama exec()
y (si eso falla) _exit()
.
Por cierto: para comprender que el almacenamiento en búfer incorrecto puede causar, aquí hay un error anterior en Linux que se ha solucionado recientemente:
El estándar requiere stderr
que no stderr
esté almacenado en búfer de manera predeterminada, pero Linux lo ignoró e hizo que la línea esté en búfer y (aún peor) esté completamente en búfer en caso de que stderr fuera redirigido a través de una tubería. Entonces, los programas escritos para UNIX produjeron cosas sin nueva línea demasiado tarde en Linux.
Vea el comentario a continuación, parece estar solucionado ahora.
Esto es lo que hago para solucionar este problema de 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);
Este código no daña en otras plataformas, ya que llamar fflush()
a una transmisión que se acaba de vaciar es un noop.
./prog1 > prog1.out
) o una tubería (./prog1 | cat
). Prepárate para alucinar. :-)