Как работает эта простая программа, связанная с вводом / выводом - PullRequest
0 голосов
/ 24 сентября 2010

Это моя программа:

#include <stdio.h>
int main(int argc, char* argv[]) {
  char buf[1024] = {0};
  setvbuf(stdout, buf, _IOFBF, 1024);
  printf("error\n");
  printf("%s\n", buf);
}

И это вывод:

error
error

Exited: ExitFailure 7

Почему строки 3 и 4 являются пустыми? Разве символ '\n' не очищает выходной буфер и не удаляется позже?

Ответы [ 4 ]

3 голосов
/ 24 сентября 2010

Звонок:

printf("error\n");

копирует "error \ n" в буфер stdout, который теперь является buf, и затем сбрасывает его на экран.

Звонок:

printf("%s\n", buf);

Затем копирует buf, который предыдущий вызов printf установил как «error \ n», чтобы снова buf, и добавляет еще один \ n к нему, так что buf теперь это «error \ n \ n», так что это где ваши 2 пустые строки родом из.

Тогда, поскольку вы не указали return 0 в конце main, возвращаемое значение из последнего вызова printf было интерпретировано как возвращаемое значение main. Поскольку "errno \ n \ n" равно 7 символам, printf вернул бы 7, а поскольку это не 0, он был интерпретирован как сбой любым, кто запустил программу.

3 голосов
/ 24 сентября 2010

Вы, конечно, вызываете неопределенное (или хотя бы неопределенное) поведение. Вы объявляете буфер и затем передаете его через setvbuf в stdout. С этого момента, буфер принадлежит stdout и больше не вам. Это означает, что вы больше не можете получить к нему доступ. Но это именно то, что вы делаете.

Я не могу доказать это из формулировки стандарта, но есть определенная комбинация параграфов, которая приводит к моему выводу.

Обновление: В ISO 799 говорится в 7.19.5.6p2 о функции setvbuf: Содержимое массива в любое время неопределенно. То, что вы видите, просто стечение обстоятельств. Вы также можете увидеть что-нибудь еще, гарантия от ISO C99 отсутствует.

Обновление 2: Поскольку содержимое массива неопределенное, все они могут также быть ненулевыми символами. И в этом случае buf больше не содержит строку . Поэтому вы явно вызываете неопределенное поведение .

1 голос
/ 24 сентября 2010

Проблема с вашим кодом состоит в том, что вы используете один буфер для совершенно разных задач - используя его в качестве промежуточного выходного буфера и используя его содержимое для печати на выход.Что делает ваша программа:

  1. Распределяет буфер `buf` и записывает` '\ 0'` в `buf [0]`, делая его пустой строкой
  2. Устанавливает I /О буфере для `buf`
  3. Записывает" error \ n "в стандартный вывод - это означает сначала` buf`, а затем, вероятно, на экран.
  4. `buf` теперь содержит строку"error \ n "
  5. Вы печатаете содержимое` buf` - это означает, что `buf` копируется в себя, что может позже вызвать странный сбой выхода.Будет напечатана вторая строка с ошибкой.

Дополнительные \ n символы, вероятно, добавлены системой.Помните, что \ n не очищает выходной буфер, вы должны вызвать функцию очистки, чтобы убедиться, что очистка произошла.

1 голос
/ 24 сентября 2010

Ваш код выхода говорит мне, что printf напечатал 7 символов - я предполагаю 5 в "error" и еще два "\ n". Может ли строка 4 быть добавлена ​​вашей ОС - какими-либо печатными буквами "Exited"?

...