Deux sorties, deux destins
Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 8 — Mémoire, fichiers et entrées-sorties
Énoncé
Ce programme écrit alternativement sur les deux sorties. On l'exécute deux fois : une fois vers le terminal, une fois avec ./prog > tout.txt 2>&1. Les deux sorties sont-elles dans le même ordre ?
for (int i = 0; i < 3; i = i + 1) {
printf("resultat %d\n", i);
fprintf(stderr, "trace %d\n", i);
}Corrigé
Non, et la mesure est catégorique. Au terminal, les six lignes s'entrelacent dans l'ordre du programme. Redirigées ensemble dans un fichier, elles sortent ainsi :
trace 0
trace 1
trace 2
resultat 0
resultat 1
resultat 2
Toutes les traces avant tous les résultats, alors que le programme les a écrites en alternance.
La cause est le tamponnage, et il dépend de la destination :
| Flux | Vers un terminal | Vers un fichier ou un tube |
|---|---|---|
| `stdout` | tampon de ligne | tampon de bloc (8 ko ici) |
| `stderr` | aucun tampon | aucun tampon |
Redirigé, stdout accumule ses trois lignes dans son tampon et ne les écrit qu'à la fin du programme ; stderr écrit immédiatement. D'où l'inversion.
Ce n'est pas un défaut, c'est le contrat : la sortie d'erreur doit parvenir même si le programme est tué à l'instant suivant — un message d'erreur perdu dans un tampon ne sert à rien. Le prix est cet ordre trompeur, et il coûte cher en mise au point : on croit lire une chronologie, on lit deux chronologies superposées.
Les deux parades. Séparer les flux — > res.txt 2> err.txt — ce qui rend chaque fichier lisible et est la raison d'être des deux sorties ; ou forcer l'écriture par fflush(stdout) avant chaque trace, ce qui rétablit l'ordre au prix d'un appel système par ligne.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.