fprintf печатает данные в неправильном порядке

#c #printf

#c #printf

Вопрос:

У меня есть программа на языке C, которая выводит некоторые данные на стандартный вывод. Я использовал printf для этого, но мне также нужно сохранить данные в файл, поэтому я изменил его на fprintf . Проблема в том, что при использовании fprintf данные располагаются в неправильном порядке, не имеет значения, является ли вывод стандартным выводом или файлом.

   if(...) {
    out = fopen(param.F, "w");
  } else {
    out = stdout;
  }

  // some code here
  fprintf(out, "a");
  // more code
  fprintf(out, "b");
  ....
  

После этого выходные данные всегда разные. Иногда это

acb

Иногда это

cab

и т.д. … Я пробовал различные комбинации setbuf и fflush, но ни одна из них не помогла.

РЕДАКТИРОВАТЬ: Возможно, важно знать, что я использую некоторые fork() в своей программе, но, как я упоминал ранее, при использовании printf проблем нет.

Вот мой вывод:

1: парикмахерская: проверяет

2: клиент 1: создан

3: клиент 1: вводит

5: парикмахер: готов

6: клиент 1: готов

4: клиент 2: создан

7: парикмахерская: закончена

8: парикмахерская: проверяет

9: клиент 2: вводит

10: клиент 1: обслужен

11: парикмахер: готов

12: клиент 2: готов

13: парикмахер: закончено

14: парикмахерская: проверяет

15: клиент 2: обслужен

Они должны быть упорядочены по номерам. Программа имеет структуру, подобную этой:

 int main() {
  pid = fork();
  if(pid == 0) {
    // barber printfs
  } else if (pid > 0) {
    // customer printfs
  } 
}
  

Комментарии:

1. Пожалуйста, опубликуйте простой тестовый пример с входными данными и ожидаемыми результатами, который показывает вашу проблему. В противном случае мы просто предполагаем.

2. Я использую fork, но он работал с printf

3. Вам нужно опубликовать весь соответствующий код. В опубликованном вами коде нет ничего изначально неправильного. (Кроме того, где печатается ‘c’?)

4. Что ж, моя проблема была «решена». У меня был особый случай входных данных, для которых выходные данные были в неправильном порядке, в остальном все работает нормально. Тем не менее, спасибо за вашу помощь!

5. звучит подозрительно, как будто у нас отсутствует тег для домашнего задания.

Ответ №1:

(Не могу прокомментировать, должен ответить …)

Нет, дело не в том, что буфер printf / fprintf отличается, объект FILE * остается тем же самым, если вы выполняете fprintf(стандартный вывод, …) или printf(….).

Несколько процессов записывают данные в один и тот же файл, и в результате отсутствия синхронизации и разной буферизации в каждом процессе выходные данные перепутаны.

Ответ №2:

у printf и fprintf будет разная буферизация драйвера устройства.

Поскольку вы говорите, что используете fork, и на основе выходных данных я делаю вывод, что код похож на

  1. Открыть файл
  2. Форк
  3. Записать данные

В этом случае возникает другой порядок, потому что запись происходит в случайном порядке, в зависимости от того, когда запланирован каждый дочерний процесс.

Самое простое решение — просто обернуть приложение в сценарий оболочки и запустить двоичный файл через tee — таким образом, все, что вы регистрируете в stdout, также отправляется в file.

Если вам нужно более сложное решение, вам нужно настроить механизм IPC между процессами и выполнять все операции записи в родительском.

Один из подходов заключается в том, чтобы установить стандартный вывод в канал (из socketpair) перед форком и прочитать из канала в родительском процессе (используя select(), чтобы избежать блокировки), затем войти в screen / file. Вам нужно будет выполнить dup() stdout перед использованием freopen, чтобы избежать его потери. Я, вероятно, пропустил несколько вещей, поскольку я не делал этого некоторое время.