fprintf后文件指针设置为NULL

时间:2014-07-23 23:29:54

标签: c linux file unix file-io

我正在使用以下代码:

void mylog(const char *fmt, ...) 
{
    static FILE *logfp = NULL;
    struct timeval  tv;
    struct timezone tz;
    struct tm      *tm;
    va_list argptr;
    char fname[256];
    extern char *__progname;

    if(logfp == NULL) {
       snprintf(fname, 256, "%s.log", __progname);
       logfp = fopen(fname, "a");
       if(logfp == NULL) {
          fprintf(stderr, "Unable to create log file.\n");
          return;
       }
    }

    va_start(argptr, fmt);
    gettimeofday(&tv, &tz);
    tm = localtime(&tv.tv_sec);
    fprintf(logfp, "%04d-%02d-%02d:%02d.%02d.%02d.%lu:",
        tm->tm_year+1900, tm->tm_mon, tm->tm_mday,
        tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec);
    vfprintf(logfp, fmt, argptr);
    va_end(argptr);
    fflush(logfp);

    if(ftell(logfp) > 256*1024) {
       fclose(logfp);
       logfp = NULL;

       /* Below - Logic to rename this log file for log rotation */
    }
}

我在vfprintf电话中发现了一次崩溃。 gdb堆栈跟踪是:

#0  _IO_vfprintf_internal (s=0x0, format=0x4a8960 "log message\n", ap=0x7fa4b4202d30) at vfprintf.c:1269

上面的代码之前没有任何问题。但是,这次崩溃对我来说很奇怪。我无法找到fprintf如何将logfp设置为NULL。 fmt设置为“log message \ n”。

3 个答案:

答案 0 :(得分:2)

我怀疑你的问题可能就是这句话:

gettimeofday(&tv, &tz);

您不会显示tz的类型,但如果它小于gettimeofday,则可能会覆盖堆栈上的其他内容(例如logfp )。覆盖后第一次访问logfp不会显示此信息,因为它可能仍然缓存在寄存器中,但在函数调用之后它必须重新加载。

您通常应该将NULL作为第二个参数传递给gettimeofday。 tz参数是一个历史错误,如果第二个参数不是NULL,现代标准会使行为未指定(甚至可能未定义?)。

答案 1 :(得分:2)

由于它是一个多线程程序,我建议你用mutex包装代码:

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

...

pthread_mutex_lock(&mutex);

/* very important code... */

pthread_mutex_unlock(&mutex);

...

答案 2 :(得分:0)

1)" fprintf()"是 NOT 将fp设置为null

2) NOT 混合' n匹配fprintf和varargs / stdargs。移动va_start()/ va_end()的fprintf OUTSIDE