我有一個MFC程序,它調用C dll在發行版中崩潰,但不在調試中。我已經嘗試使用fprintf將消息寫入文件,並且這適用於程序的第一遍。但是,程序第二次運行計算時會崩潰。調試MFC程序使用fprintf調用C DLL
在寫入C例程頂部的第一個可執行語句之後,立即關閉調試日誌文件。信息在第一次計算後寫入日誌文件,但不在第二次計算期間。
有什麼建議嗎?
我有一個MFC程序,它調用C dll在發行版中崩潰,但不在調試中。我已經嘗試使用fprintf將消息寫入文件,並且這適用於程序的第一遍。但是,程序第二次運行計算時會崩潰。調試MFC程序使用fprintf調用C DLL
在寫入C例程頂部的第一個可執行語句之後,立即關閉調試日誌文件。信息在第一次計算後寫入日誌文件,但不在第二次計算期間。
有什麼建議嗎?
當處理這種類型的問題時,我需要有一個日誌工具,我通常會編寫一個函數來調用日誌記錄。然後我把這個函數包裝在一個宏中,這個宏允許我啓用或禁用日誌記錄。作爲其中的一部分,我有時也會使用一個調試級別指示器,因此並非所有日誌都將放入日誌文件中。
日誌記錄功能本身將作爲一個單獨的小型庫文件。將會有一個include文件包含日誌庫函數原型和一個宏來啓用或禁用日誌記錄。
我發現有些東西可能對日誌有所幫助,具體取決於應用程序的類型,例如將每個日誌的時間標記爲秒或毫秒。我還發現,使用標準的行長度可以在文本編輯器中更輕鬆地查看日誌。對源文件的路徑以及源代碼行有一些瞭解可能會非常有幫助。
下面的代碼是自由寫的,並沒有經過測試,甚至沒有編譯,所以可能會有一個或兩個錯誤。
實際的記錄功能,可以把它叫做LogWriteLog()
會被包裹在一個宏如下:
#define LOGISSUELOG(level,logtext) LogWriteLog(level, logtext, __FILE__, __LINE__);
通過使用宏您可以啓用或通過改變宏定義禁用日誌記錄。該宏也會自動生成源文件的路徑和日誌的源代碼行號。
爲此,我希望將變量作爲日誌的一部分時,有時會將其包含到以下預處理器代碼序列中。大括號允許將多行插入源代碼中,並具有本地範圍的char變量。
#if defined(LOGISSUELOG)
{
char xBuff[128];
sprintf (xBuff, "value 1 %d, error %d", iValue, iErrorStatus);
LOGISSUELOG(4, xBuff);
}
#endif
簡單的日誌庫將只有幾個功能,一個打開日誌文件,並指定調試級別,完成後第二個真正做一個記錄,而第三關閉日誌文件。
使用標準的C I/O例程,實際的日誌記錄功能如下所示。您也需要string.h
和stdio.h
。此外,您可能需要考慮每次重新啓動時是否要截斷文件,或者是否要對文件執行附加操作。
我也做過這個檢查文件的大小,當它達到一定的大小到fseek()
到文件的開始環繞。如果你正在環繞,時間戳變成幾乎是必需的。如果進行換行,確實會使所有日誌行的標準行寬變得有必要,以便事物排列齊整。
// allocate the file scope globals used by the logging library
static FILE *fpLogWriteLog = 0;
static int iLogDebugLevel = 0;
int LogOpenLog (int iDebugLevel, char *aszLogFilePath)
{
// open the log file for writing, truncating what is there already
fpLogWriteLog = fopen (aszLogFilePath, "w");
iLogDebugLevel = iDebugLevel;
return (fpLogWriteLog == 0) ? 0 : 1;
}
void LogCloseLog (void)
{
if (fpLogWriteLog)
fclose (fpLogWriteLog);
}
// allow the debug logging level to be changed.
//return the current value so that it can be used in another call to set it back.
int LogChangeLogLevel (int iDebugLevelNew)
{
int iDebugLevelSave = iLogDebugLevel;
iLogDebugLevel = iDebugLevelNew;
return iDebugLevelSave;
}
// write a log to the log file
int LogWriteLog (int iDebugLevel, char *aszLogText, char *aszFileName, int iLineNo)
{
int iRetStatus = 0;
if (fpLogWriteLog && iDebugLevel < iLogDebugLevel) {
int iLen = strlen (aszFileName);
// we will keep only the last 30 characters of the source file path
if (iLen > 30)
iLen = 30;
else
iLen = 0;
// use print specifiers to provide the same line width for the output log
// use %-60.60s to print log text in case of print format specifiers in it
fprintf (fpLogWriteLog, "%3.3d %-30.30s - %6.6d: %-60.60s", iDebugLevel, aszFileName + iLen, iLineNo, aszLogText);
fflush (fpLogWriteLog);
iRetStatus = 1;
}
return iRetStatus;
}
一些代碼示例可能嗎? – 2012-07-31 14:26:19
我發現我可以添加下面的代碼: FILE * fp; fp = fopen(「c:\\ temp \\ debugP2.txt」,「w」); 到有問題的例程的頂部打開一個文件,然後移動此代碼: fprintf(fp,「check P22 \ r \ n」); fclose(fp);一行一行地按線路逐行調試。如果「檢查P22」沒有寫入文件,那麼我已經通過了存在該錯誤的點。這很麻煩,因爲文件必須在錯誤發生之前關閉,或者沒有任何文件被寫入文件。 FORTRAN並非如此。 – 2012-07-31 17:46:28
這並不奇怪,你可以在關閉文件之前先執行「fflush(fp)」,以確保緩衝區中沒有任何內容。另外檢查「fp」是否爲空。 – 2012-07-31 21:23:15