Безопасно ли отключать буферизацию с помощью stdout и stderr? - PullRequest
9 голосов
/ 11 февраля 2012

Иногда мы помещаем отладочные отпечатки в наш код таким образом

printf("successfully reached at debug-point 1\n"); 

some code is here

printf("successfully reached at debug-point 2"); 

Here segmantaion fault occur due to some reason 

Теперь в этом состоянии только debug-point1 будет печататься на stdio. Debug-point 2 print был записан в буфер stdio, но не очищен, поскольку не получил \n, поэтому мы считаем, что сбой произошел после debug-point1

, чтобы перебраться из этого, если я отключу буферизацию с потоком stdio и stderr следующим образом

setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);

тогда безопасно ли это делать?

почему весь поток по умолчанию буферизуется в строке?

Редактировать:

Каков размер выделенного по умолчанию буфера для любого файлового потока? Я думаю, что его ОС зависела. я хотел бы знать о Linux?

Ответы [ 5 ]

6 голосов
/ 11 февраля 2012

Возможным способом может быть глобальный флаг bool dodebug и определение макроса, например,

#ifdef NDEBUG
#define debugprintf(Fmt,...) do{} while(0)
#else
#define debugprintf(Fmt,...) do {if (dodebug) {                 \
   printf("%s:%d " Fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
   fflush(stdout); }} while(0)
#endif

Тогда внутри вашего кода есть немного

debugprintf("here i=%d", i);

Конечно, в приведенном выше макросе можно вместо этого сделать fprintf ... Обратите внимание на fflush и добавленную новую строку в формате.

Отключение буферизации, вероятно, следует избегать по соображениям производительности.

6 голосов
/ 11 февраля 2012

почему все потоки по умолчанию буферизуются в строке

Они буферизуются по соображениям производительности.Библиотека старается избежать системного вызова, потому что это занимает много времени.И не все из них буферизируются по умолчанию.Например, stderr является , как правило, небуферизованным, а stdout буферизуется строкой, только когда он ссылается на tty.

тогда безопасно ли это делать?

Безопасно отключать буферизацию, но я должен сказать, что это не лучший метод отладки.

2 голосов
/ 11 февраля 2012

Если ваша программа записывает много выходных данных, отключение буферизации, вероятно, сделает ее в 10-1000 раз медленнее.Это обычно нежелательно.Если ваша цель - просто согласованность вывода при отладке, попробуйте добавить явные вызовы fflush там, где вы хотите сбросить вывод, а не отключать буферизацию глобально.И желательно не писать код сбоя ...

2 голосов
/ 11 февраля 2012

Это «безопасно» в одном смысле и небезопасно в другом. Небезопасно добавлять отладочные printfs и по той же причине небезопасно добавлять код для изменения буферизации stdio в том смысле, что это кошмар обслуживания То, что вы делаете, НЕ является хорошей техникой отладки. Если ваша программа получает ошибку, вам просто нужно проверить дамп ядра, чтобы увидеть, что произошло. Если этого недостаточно, запустите программу в отладчике и выполните шаги, чтобы выполнить действие. Это звучит сложно, но на самом деле это очень просто и является важным навыком. Вот образец:

$ gcc -o segfault -g segfault.c   # compile with -g to get debugging symbols
$ ulimit -c unlimited             # allow core dumps to be written
$ ./segfault                      # run the program
Segmentation fault (core dumped)
$ gdb -q segfault /cores/core.3632  # On linux, the core dump will exist in
                                    # whatever directory was current for the
                                    # process at the time it crashed.  Usually
                                    # this is the directory from which you ran
                                    # the program.
Reading symbols for shared libraries .. done
Reading symbols for shared libraries . done
Reading symbols for shared libraries .. done
#0  0x0000000100000f3c in main () at segfault.c:5
5               return *x;          <--- Oh, my, the segfault occured at line 5
(gdb) print x                       <--- And it's because the program dereferenced
$1 = (int *) 0x0                     ... a NULL pointer.
2 голосов
/ 11 февраля 2012

Ну, хорошо. Вы ошибаетесь. Именно по этой причине stderr является не буферизованным по умолчанию.

РЕДАКТИРОВАТЬ: Кроме того, как общее предложение,попробуйте использовать точки останова отладчика вместо printf s.Делает жизнь намного проще.

...