0

リリースではクラッシュするがデバッグではクラッシュしない C dll を呼び出す MFC プログラムがあります。fprintf を使用してメッセージをファイルに書き込もうとしましたが、これはプログラムの最初のパスで機​​能します。ただし、プログラムが計算を 2 回実行すると、プログラムはクラッシュします。

C ルーチンの先頭にある最初の実行可能ステートメントとしてデバッグ ログ ファイルに書き込んだ直後に、デバッグ ログ ファイルを閉じます。情報は最初の計算後にログ ファイルに書き込まれますが、2 回目の計算中は書き込まれません。

助言がありますか?

4

1 に答える 1

0

ロギング機能が必要なこの種の問題に取り組むとき、私は通常、ロギングのために呼び出す関数を作成します。次に、ロギングを有効または無効にできるマクロで関数をラップします。この一環として、すべてのログがログ ファイルに書き込まれないように、デバッグ レベル インジケーターも使用することがあります。

ロギング関数は、個別の小さなライブラリとして単独でファイルに含まれます。ロギング ライブラリ関数のプロトタイプと、ロギングを有効または無効にするマクロを含むインクルード ファイルがあります。

各ログのタイムスタンプを秒単位またはミリ秒単位にするなど、アプリケーションの種類によっては、ログに役立つことがいくつかあることがわかりました。また、標準的な行の長さを使用すると、テキスト エディターでログを確認しやすくなることもわかりました。ソース ファイルのパスとソース行番号を把握しておくと、非常に役立ちます。

次のコードはフリーハンドで書かれており、テストもコンパイルもされていないため、1 つまたは 2 つのエラーがある可能性があります。

実際のロギング関数は、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

単純なログ ライブラリには、ログ ファイルを開いてデバッグ レベルを指定する関数、実際にログを作成する関数、完了時にログ ファイルを閉じる関数の 2 つしかありません。

標準の CI/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-08-10T01:43:01.723 に答える