2012-07-31 64 views
0

我有一個MFC程序,它調用C dll在發行版中崩潰,但不在調試中。我已經嘗試使用fprintf將消息寫入文件,並且這適用於程序的第一遍。但是,程序第二次運行計算時會崩潰。調試MFC程序使用fprintf調用C DLL

在寫入C例程頂部的第一個可執行語句之後,立即關閉調試日誌文件。信息在第一次計算後寫入日誌文件,但不在第二次計算期間。

有什麼建議嗎?

+0

一些代碼示例可能嗎? – 2012-07-31 14:26:19

+0

我發現我可以添加下面的代碼: 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

+0

這並不奇怪,你可以在關閉文件之前先執行「fflush(fp)」,以確保緩衝區中沒有任何內容。另外檢查「fp」是否爲空。 – 2012-07-31 21:23:15

回答

0

當處理這種類型的問題時,我需要有一個日誌工具,我通常會編寫一個函數來調用日誌記錄。然後我把這個函數包裝在一個宏中,這個宏允許我啓用或禁用日誌記錄。作爲其中的一部分,我有時也會使用一個調試級別指示器,因此並非所有日誌都將放入日誌文件中。

日誌記錄功能本身將作爲一個單獨的小型庫文件。將會有一個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.hstdio.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; 
    }