调试打印函数

有时程序出了原因不明的问题,缺乏必要的运行日志供分析,而环境又没提供调试工具来跟踪,要想知道更多的程序运行时细节,简单粗暴的方法就是将感兴趣的内容都打印出来,该做法的缺点是得重新编译文件做替换。

对于简单的console程序,可以直接将内容输出到终端,对于比较复杂的程序,建议输出到磁盘文件中。

static void ulog(const char *fmt, ...) {
    FILE *fp = fopen("ulog.txt", "a");
    va_list ap;
    va_start(ap, fmt);
    vfprintf(fp, fmt, ap);
    va_end(ap);
    fprintf(fp, "\n");
    fclose(fp);
}

上述接口已能满足大部分调试要求,但对于性能调优,需要增加时间项;对于多进程多线程,可考虑加上进程ID或线程ID。

static void ulog(const char *fmt, ...)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    struct tm *tm = localtime(&tv.tv_sec);

    FILE *fp = fopen("ulog.txt", "a");
    fprintf(fp, "%02d:%02d:%02d.%03d ",
        tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec / 1000);
    va_list ap;
    va_start(ap, fmt);
    vfprintf(fp, fmt, ap);
    va_end(ap);
    fprintf(fp, "\n");
    fclose(fp);
}

对于简单使用场景,也可以通过宏来实现。

#define ulog(fmt, ...) {\
    FILE *fp = fopen("ulog.txt", "a");\
    fprintf(fp, "[%04d] %s:%d (%s) $ "fmt"\n", getpid() % 10000,\
        __FILE__, __LINE__, __func__, ##__VA_ARGS__);\
    fclose(fp);\
}
Table of Contents