使用stdout和stderr禁用缓冲是否安全?

时间:2012-02-11 07:26:22

标签: c linux stdout stderr buffering

有时我们会在代码中添加一些调试打印

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

some code is here

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

Here segmantaion fault occur due to some reason 

现在在这种情况下只有debug-point1将在stdio上打印调试点2打印被写入stdio缓冲区但是它没有刷新,因为它没有得到\n因此我们认为在debug-point1之后发生崩溃< / p>

如果我用这样的方式禁用stdio和stderr流的缓冲选项

setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
那么这样做是否安全?

为什么所有流都默认为行缓冲?

修改:

通常,对于任何文件流,默认分配缓冲区的大小是多少?我认为它的依赖。我想知道Linux?

5 个答案:

答案 0 :(得分:6)

可能的方法是拥有一个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以及格式的附加换行符。

出于性能原因,应该避免禁用缓冲。

答案 1 :(得分:5)

  

为什么所有流都默认为行缓冲

出于性能原因,它们是缓冲的。库努力避免进行系统调用,因为它需要很长时间。并非所有这些都默认缓冲。例如,stderr 通常无缓冲,stdout仅在引用tty时才进行行缓冲。

  那么这样做是否安全?

禁用缓冲是安全的,但我必须说这不是最好的调试技术。

答案 2 :(得分:2)

呃,好吧。 你错了。正是因为这个原因,默认情况下 stderr 缓冲。

编辑: 另外,作为一般建议,请尝试使用调试器断点而不是printf。让生活更轻松。

答案 3 :(得分:2)

从某种意义上说它是“安全的”,而在另一种意义上则是不安全的。添加调试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.

答案 4 :(得分:2)

如果你的程序写了很多输出,禁用缓冲可能会使它慢大10到1000倍。这通常是不合需要的。如果您的目标只是在调试时输出的一致性,请尝试添加明确的fflush调用,以便在需要刷新输出的同时全局关闭缓冲。最好不要写崩溃的代码......