我一直未能找到以下問題的答案,而且我遇到了一些與這些功能相關的問題。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