[英]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之后發生崩潰。
如果我以這種方式禁用stdio
和stderr
流的緩沖選項
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.