我一直未能找到以下问题的答案,而且我遇到了一些与这些功能相关的问题。C++中fprintf和vfprintf有什么区别?
我的主要编程是用C#完成的,在学习时从来没有真正学过C++,但是在我目前的工作中,我还必须做一些C++编程。
大部分的C++编程都是由一名前员工完成的,他为登录做了一个功能。
偶尔此功能导致错误(访问冲突) - 这不会显示给用户,但我通过调试器运行代码时看到它。
在错误发生时它指向这行代码:
vfprintf(LogFile, fmt, va);
然后我把在代码仔细看看之前和之后,并把上面到上下文的代码解决办法是:
void FileLog(char *fmt, ...)
{
va_list va;
struct time t;
struct date d;
long clk;
static int ReEntrant = 0;
if(FileLogEnabled == false)
return;
ReEntrant++;
if(ReEntrant > 1)
return;
if(LogFile == NULL)
LogFile = fopen(LogFileName, "a+");
if(LogFile != NULL)
{
gettime(&t);
getdate(&d);
fprintf(LogFile, "\n%d-%02d-%02d %2d:%02d:%02d.%02d0> ", d.da_year, d.da_mon, d.da_day, t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);
va_start(va, fmt);
vfprintf(LogFile, fmt, va);
va_end(va);
fflush(LogFile);
...
}
ReEntrant = 0;
}
其实我不明白为什么它需要(如果是?)同时调用fprintf和vfprintf?我会认为第一个fprintf调用会将格式化的字符串写入流(File),那就足够了?
一点解释或者一些信息,将不胜感激:)
编辑:从号注释后 - 我追查到今天经常被造成这个错误的函数的特定呼叫。
FileLog("TimerRestore[%d], Name=%s", Package.CurGame->Timers[ Index ].Name.c_str());
我确实认为这可能带来一些麻烦,因为“TimerRestore [%d],名称=%s”时应该遵循一个十进制和字符串arguemtn,但只有一个字符串给出参数。我需要做一些测试,但是我相信谁写这段代码的作者的意思是写:
FileLog("TimerRestore[%d], Name=%s", Index, Package.CurGame->Timers[ Index ].Name.c_str());
不过我还是不明白,为什么函数调用不似乎总是导致错误。或者,也许这是FileLog函数中的“ReEntrant”变量的原因,当它没有失败时,它会阻止它?
非常感谢所有的反馈和信息。
请不要将C++和C绑定在一个假的术语“C/C++”中。他们是不同成语的不同语言。 –
这个日志记录函数是从多个线程中调用的吗? “gettime”和“getdate”函数中是否有任何静态参数? – paddy
如果您查看代码,则第一次fprintf()调用仅将日期/时间写入日志文件。 vfprintf()调用打印实际的日志消息。如果调用者为日志消息提供了自己的格式化字符串,则这些不能组合。但是,实际的错误不在调试器停止的那一行,这是因为有人用无效的参数调用了这个函数,你必须跟踪这个参数。 – nos