LINUX.ORG.RU

[C] stdout - как «правильно» с ним работать?

 


0

0

Когда просто выводим "Hello world" в stdout и завершаем работу программы - тут все ясно, но если программа ПРОДОЛЖАЕТ выполняться, то получается интересный фокус:

/***** begin test.c *****/
#include <stdio.h>

int main () {
char c;
fprintf(stdout, "Hello world!\n");
c = fgetc(stdin);
return 0;
}
/***** end test.c *****/

$ make test
$ ./test
c
Hello world!
$ ./test > 1
$ ^C
$ cat 1
$

Как видим, если аварийно (по Ctrl-C) завершить работу программы, то никакого "Hello world!" в файле "1" не будет. Хотя код вывода "Hello world" отработал. Как сделать так, чтобы перенаправление в файл работало корректно, в унисон с кодом программы?


В примере комманд опечатка. Вот подправленный вариант:

$ make test
$ ./test
Hello world!
c
$ ./test > 1
$ ^C
$ cat 1
$

s0ldat
() автор топика

для деббага использовать stderr -- он не буфферится

beastie ★★★★★
()

Я вам больше скажу.



 #include <stdio.h>

int main () {
      char c;
         FILE* fl;
        fl = fopen("i.txt", "wt");
        fprintf(fl, "Hello world!\n");
         //fclose(fl);
        c = fgetc(stdin);
           return 0;
} 


Тоже самое.  Если раскомментировать fclose то будет писать. Как то так. 

Dudraug ★★★★★
()
Ответ на: комментарий от Dudraug

1) вы не проверяете что вернет open.

2) вы не проверяете что вернет fprintf

3) вы не проверяете что вернет close

И то что у вас работает, это, называется, повезло. close() не обязательно делает sync для fs, лучше делать fsync. Да, проверять ее код возврата тоже надо :)

catap ★★★★★
()
Ответ на: комментарий от Dudraug

Пример как не надо писать программы.

А потом все удивляются почему это никто не проверяет что вернул close().

Блин.

catap ★★★★★
()
Ответ на: комментарий от catap

> лучше делать fsync С учётом того что на ext3 оно синкнет вообще всё я бы не стал этого делать.

> А потом все удивляются почему это никто не проверяет что вернул close().

А что делать если close вернул ошибку? какие ошибки у тебя он возвращал? Я вижу в мане всего 3. Из них EBADF это явная ошибка программирования(попытка закрыть не открытый дескриптор), EIO это проблемы с диском/сетью итд что, с моей точки зрения, на совести юзера а не программы и, скорее всего, всплывёт гораздо раньше(на open/read/write) а не под самый конец. А про EINTR написано сдесь: http://lkml.indiana.edu/hypermail/linux/kernel/0207.2/1563.html

true_admin ★★★★★
()
Ответ на: комментарий от dilmah

>Epic Fail started there.

Можно подробнее, если запустишь текст приведенный мною, то при нажатие ctrl+c до fclose текст записан не будет. Можешь даже в примере топикстартера сделать fclose(stout); Или ты видишь принципиальную разницу между стандартным потоком вывода и потоком ассоциированным с файлом на фс?

Dudraug ★★★★★
()
Ответ на: комментарий от true_admin

EIO еще может появиться, когда внезапно кончилось место. Т.е. мы записали в буфер а при close() при sync оно бах, и кончилось.

catap ★★★★★
()
Ответ на: комментарий от catap

>Пример как не надо писать программы.

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

>А потом все удивляются почему это никто не проверяет что вернул close().

Если уж придираться могу заметить что close != fclose и open != fopen.

Еще замечу, что проверка fclose не даст ничего если файл был удален после открытия, но до закрытия. А это на мой взгляд наиболее возможная проблема. Проблемы с железом на локальной фс роли почти не играют.

Dudraug ★★★★★
()
Ответ на: комментарий от catap

ну ок, что дальше делать программе? Как ты в своих программах это обрабатываешь? Должны ли программы типа cat что-то делать в этом случае?

true_admin ★★★★★
()
Ответ на: комментарий от catap

Ладно, cat погорячился

Ну а что на счёт остальных вопросов? Если ты ловишь ошибку то значит ты её должен обрабатывать. Возьмём nginx. Вроде как на возвращаемое значение там смотриться, но ничего не делается. Нужна ли такая проверка? И вообще непонятно почему он не сделал close_with_notify() вместо того чтобы писать if (close(fd) == -1) { ngx_log_error(); }. Почему я привёл в качестве примера догадайся сам :)

true_admin ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.