J'ai un programme C qui compile un exécutable appelé myprogram. C'est sa fonction principale:
int main(int argc, char ** argv) {
printf("this is a test message.\n");
system("ls");
return 0;
}
Lorsque j'exécute myprogram > output.txt
dans un shell Linux, puis que j'examine output.txt, la sortie de ls
est répertoriée ci-dessus. Il s'agit d'un message de test.
Je pense que ce devrait être l'inverse. Pourquoi cela se produit-il et que puis-je faire pour que "ceci soit un message de test" apparaisse en haut du fichier output.txt?
Si cela compte, je suis nouveau dans C et travaille dans une ligne de commande.
Par défaut, stdout
affiche line-buffered lorsqu’il est connecté à un terminal. Autrement dit, le tampon est vidé lorsqu'il est plein ou lorsque vous ajoutez une nouvelle ligne.
Cependant , si stdout
n'est pas connecté à un terminal, comme ce qui se produit lorsque vous redirigez la sortie de votre programme vers un fichier , alors stdout
devient entièrement mis en mémoire tampon. Cela signifie que le tampon sera vidé et effectivement écrit, soit lorsqu'il sera plein, soit lorsqu'il sera explicitement vidé (ce qui se produit lorsque le programme se ferme).
Cela signifie que la sortie d'un processus séparé démarrant à partir de votre code (comme ce qui se passe lorsque vous appelez system
) sera probablement écrite en premier, car la mémoire tampon de ce processus sera vidée à la fin du processus, ce qui est antérieur à votre propre processus.
Que se passe-t-il lors de l'utilisation de la redirection (ou des pipes d'ailleurs):
printf
écrit dans la mémoire tampon stdout
.system
démarre un nouveau processus, qui écrit dans son propre tampon.system
) se termine, sa mémoire tampon est vidée et écrite. Votre propre tampon dans votre propre processus, n'est pas touché.stdout
est vidé et écrit.Pour obtenir la sortie dans l'ordre "correct" (ou du moins attendu), appelez fflush
avant d'appeler system
, pour vider explicitement stdout
ou appelez setbuf
avant toute sortie pour désactiver complètement la mise en mémoire tampon.
Il est lié à la mise en mémoire tampon de sortie. J'ai réussi à reproduire le même comportement. Forcer le flush l'a fait pour moi.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char ** argv) {
printf("this is a test message.\n");
fflush(stdout);
system("ls");
return 0;
}
Avant d'ajouter le fflush:
$ ./main > foo
$ cat foo
main
main.c
this is a test message.
et après:
$ ./main > foo
$ cat foo
this is a test message.
foo
main
main.c
J'imagine que c'est à cause de l'ordre dans lequel le tampon stdout est vidé, ce qui n'est pas nécessairement déterministe. Il est possible que le parent engendre le processus ls
et qu'il ne vide pas sa propre sortie standard avant son retour. En fait, il est possible que la vidange ne soit pas vidée avant la fin du processus.
Essayez d'ajouter fflush (stdout)
après l'instruction printf et voyez si cela force la sortie à apparaître en premier.