Результаты printf () и system() находятся в неправильном порядке, когда вывод перенаправляется в файл [дубликат]


этот вопрос уже есть ответ здесь:

у меня есть программа на C, которая компилируется в исполняемый файл под названием myprogram. Это его основная функция:

int main(int argc, char ** argv) {
  printf("this is a test message.n");
  system("ls");

  return 0;
}

когда я запускаю myprogram > output.txt в оболочке Linux, а затем проверить вывод.txt, я вижу выход ls перечисленные выше "это тестовое сообщение."

Я чувствую, что это должно быть наоборот. Почему это происходит, и что я могу сделать, чтобы "это тестовое сообщение" появилось в верхней части вывода.txt?

Если это имеет значение, Я новичок как в C, так и в работе в командной строке.

3 83

3 ответа:

по умолчанию для stdout и линия-буферизованный при подключении к терминалу. То есть буфер сбрасывается, когда он заполнен или когда вы добавляете новую строку.

, если stdout не подключен к терминалу, как что происходит, когда вы перенаправить вывод программы в файл, а затем stdout становится полностью буферизованной. Это означает, что буфер будет сброшен и фактически записан либо когда он полный или при явном сбросе (что происходит при выходе из программы).

это означает, что вывод отдельного процесса запускается из вашего кода (например, что происходит при вызове system), скорее всего, будет записан первым, так как буфер этого процесса будет сброшен, когда этот процесс закончится, что до вашего собственного процесса.

что происходит при использовании перенаправления (или трубы, если на то пошло):

  1. код printf вызов записывает в stdout буфера.
  2. The system функция запускает новый процесс, который записывает в свой собственный буфер.
  3. когда внешний процесс (создана system вызов) выходит, его буфер очищается и записывается. Ваш собственный буфер в вашем собственном процессе, не трогается.
  4. ваш собственный процесс заканчивается, и ваш stdout буфер сбрасывается и написано.

чтобы получить вывод в "правильном" (или, по крайней мере, ожидаемом) порядке, вызовите fflush перед вызовом system, явно флаш stdout, или позвонить setbuf перед любым выходом полностью отключить буферизацию.

это связано с буферизацией вывода. Мне удалось воспроизвести то же самое поведение. Форсирование смыва сделало это за меня.

#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;
}

перед тем, как добавить функцию fflush:

$ ./main > foo
$ cat foo
main
main.c
this is a test message.

и после:

$ ./main > foo
$ cat foo
this is a test message.
foo
main
main.c

Я подозреваю, что это из-за порядка, в котором буфер stdout сбрасывается, что не обязательно детерминировано. Вполне возможно, что родитель порождает ls process и не сбрасывает свой собственный stdout до тех пор, пока он не вернется. Он не может фактически очистить stdout, пока процесс не завершится.

попробуйте добавить fflush (stdout) после оператора printf и посмотреть, если это заставляет вывод появиться первым.