繁体   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