微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么以及如何redirectdebugging语句?

我想知道为什么最好将debugging语句redirect到stderr,就像在这里完成的那样:

#ifdef DEBUG_TEST #define DEBUG_TEST 1 #else #define DEBUG_TEST 0 #endif #define DEBUG_PRINT(fmt,...) do { if (DEBUG_TEST) fprintf(stderr,fmt,##__VA_ARGS__); } while (0)

另外:我们如何将这些debugging语句redirect到一个单独的日志文件并在该文件加上时间戳? 我想在我的代码中使用一个macros做这个。

平台:Linux,gcc编译器

Profinet / Profibus linux

EXE或DLL图像基地址

创build一个Windows驱动程序,透明地encryption和解密用户文件

Linux,C ++,ThirdParty库

我怎样才能读取条形码,而不用让用户先把文本对焦呢?

fork()系统调用c

将GetClassInfo从HINSTANCE调用到外部窗口是不恰当的?

向_beginThreadEx传递多个参数

如何检查远程主机和本地和UNCpath上的访问权限?

使用waitpid等待另一个进程的线程

我可以给你两个为什么你会这样做的例子:你可以很容易地将标准输出重定向一个文件,同时在你的终端保持标准错误(这似乎正是你想要做的第二个问题)。 您的工具可能会突出显示发送到stderr的邮件,以便马上找到它们。

您可以使用命令行版本来重定向标准错误,正如同样的建议。 要获取文件名中的时间戳,在运行程序时可以这样做:

./program 2>"logfile-`date`.txt"

如果你想在程序本身做到这一点,一种方法是简单地使用fopen打开另一个文件并写入。 这里有一个可以玩的完整的例子:

#include <time.h> #include <stdlib.h> #include <stdio.h> #include <stdbool.h> #define DEBUG_TEST true FILE *debug_file; #define DEBUG_PRINT(fmt,...) do { if (DEBUG_TEST) fprintf(debug_file,##__VA_ARGS__); } while (false); int main() { time_t timestamp = time(NULL); char * s = malloc(snprintf(NULL,"debug-%d.txt",timestamp)); sprintf(s,timestamp); debug_file=fopen(s,"w"); DEBUG_PRINT("YEAHn"); fclose(debug_file); return EXIT_SUCCESS; }

使用stderr优于stdout的好处是,如果您将输出重定向一个文件或将其(使用管道)流式传输到另一个进程,调试消息不会妨碍您的工作。

如果你想把stderr重定向到Unix上的文件,你可以像这样运行你的程序:

./program 2>logfile

您将调试信息报告给stderr而不是stdout原因之一是, stdout可能会在管道中发送,诊断将与实际数据一起发送,从而导致流水线后续阶段的混淆。

如果您可能想要重定向输出,或添加时间戳(或PID,或任何其他信息),则不要直接使用fprintf() 。 调用你自己设计的功能,以你想要的方式处理你想要的信息。

因此,你的宏可以是:

extern void dbg_print(const char *fmt,...); #define DEBUG_PRINT(fmt,...) do { if (DEBUG_TEST) dbg_print(fmt,__VA_ARGS__); } while (0)

要么:

extern void dbg_print(const char *func,const char *file,int line,const char *fmt,...) do { if (DEBUG_TEST) dbg_print(__func__,__FILE__,__LINE__,__VA_ARGS__); } while (0)

包括信息中的函数名称文件名和行号

例如,我有一个适度复杂的包,这样做。 核心内部例程之一是:

/* err_stdio - report error via stdio */ static void err_stdio(FILE *fp,int flags,int errnum,const char *format,va_list args) { if ((flags & ERR_NOARG0) == 0) fprintf(fp,"%s: ",arg0); if (flags & ERR_STAMP) { char timbuf[32]; fprintf(fp,"%s - ",err_time(timbuf,sizeof(timbuf))); } if (flags & ERR_PID) fprintf(fp,"pid=%d: ",(int)getpid()); vfprintf(fp,format,args); if (flags & ERR_ERRNO) fprintf(fp,"error (%d) %sn",errnum,strerror(errnum)); }

调试包装可以使用适当的标志调用函数,并生成所需的输出。 系统的其他部分控制使用的文件流( stderr是认的,但有一个函数可以将输出重定向到任何其他的流),依此类推。

如果通过直接在调试宏中使用fprintf()来限制自己,那么你就会被fprintf()所能做的事情所困住,或者重新编译所有的东西。

有关调试宏以及如何使用它们的更多信息,请参阅我对“调试打印的C#定义宏”的回答(虽然看起来好像你已经在板上说了很多东西了)。

原谅如果我错了,但似乎没有人提到缓冲。

认情况下,stdout在大多数平台上是行缓冲的,stderr是无缓冲的。 基本上这意味着,认情况下,写入标准输出写入内存,并写入文件或控制台,因为逐字输出是慢慢的。

如果你正在调试,你不希望消息出现得太晚,那么你实际上是打印它(甚至可能永远不会打印,如果你的程序崩溃或卡住在一个无限循环(当你认为这可以真的搅乱你它的循环或崩溃在错误的地方),你通常不介意速度的打击,理论上可以由于时间和同步错误而有所作为,但是在任何情况下都很难捕捉/调试。

TL;当打印到stderr而不是标准输出(其他人可能建议记录到一个文件,或者允许运行时选项,如启用/禁用打印文件,样式,阈值等)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐