Безопасно ли отключить буферизацию с помощью stdout и stderr?

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

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

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 stream, как этот путь

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

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

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

Edit:

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

5 ответов


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

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

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

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


возможный способ может быть иметь 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);

конечно, вы могли бы, в макро выше, сделать ... Обратите внимание на fflush и добавленная новая строка в формат.

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


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

изменить: Кроме того, в качестве общего предложения попробуйте использовать точки останова отладчика вместо printfs. Делает жизнь намного проще.


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

$ 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
 = (int *) 0x0                     ... a NULL pointer.

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