簡體   English   中英

使用stdout和stderr禁用緩沖是否安全?

[英]Is it safe to disable buffering with stdout and stderr?

有時我們會以這種方式在代碼中添加一些調試打印

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

some code is here

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

在最后一次printf之后發生分段錯誤。

現在在這種情況下只有debug-point1將在stdio上打印調試點2打印被寫入stdio緩沖區,但它沒有刷新,因為它沒有得到\\n因此我們認為在debug-point1之后發生崩潰。

如果我以這種方式禁用stdiostderr流的緩沖選項

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

那么,這樣做是否安全?

為什么默認情況下所有流都緩沖?

編輯:

通常,對於任何文件流,默認分配緩沖區的大小是多少? 我認為這取決於操作系統。 我想知道Linux。

為什么所有流都默認為行緩沖

出於性能原因,它們是緩沖的。 庫努力避免進行系統調用,因為它需要很長時間。 並非所有這些都默認緩沖。 例如, stderr 通常是無緩沖的, 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);

當然,你可以在上面的宏中改為fprintf ...注意fflush和格式的附加換行符。

出於性能原因,應該避免禁用緩沖。

呃,好吧。 你錯了。 正是由於這個原因,默認情況下stderr 沒有緩沖。

編輯:此外,作為一般建議,嘗試使用調試器斷點而不是printf 讓生活更輕松。

它在某種意義上是“安全的”,在另一種意義上是不安全的。 添加調試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.

如果你的程序寫了很多輸出,禁用緩沖可能會使它慢大10到1000倍。 這通常是不合需要的。 如果您的目標只是調試時輸出的一致性,請嘗試在需要刷新輸出的地方添加顯式fflush調用,而不是全局關閉緩沖。 最好不要寫崩潰的代碼......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM