[英]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.