有时我们会在代码中添加一些调试打印
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?
答案 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)
编辑:
另外,作为一般建议,请尝试使用调试器断点而不是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
调用,以便在需要刷新输出的同时全局关闭缓冲。最好不要写崩溃的代码......