我正在使用以下代码:
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”。
答案 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 。