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" отработал. Как сделать так, чтобы перенаправление в файл работало корректно, в унисон с кодом программы?

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

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

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

s0ldat ()

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

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

beastie ★★★★★ ()

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

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



 #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 ★★★★★ ()
Ответ на: Re: [C] stdout - как "правильно" с ним работать? от Dudraug

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

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

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

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

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

catap ★★★★★ ()

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

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

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

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

true_admin ★★★★★ ()

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

>Epic Fail started there.

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

Dudraug ★★★★★ ()

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

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

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

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

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

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

Dudraug ★★★★★ ()

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

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

true_admin ★★★★★ ()

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

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

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

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