2

最新の FastMM4 4.991、XE2 はメモリ リークを解決しようとしており、FullDebugMode + LogErrorsToFile 設定でこのエラーが発生しました。エラー

The current thread ID is 0x7C4, and the stack trace (return addresses) leading to this error is:
41B914 [FastMM4][CheckFreeBlockUnmodified$qqrrp29Fastmm4.TFullDebugBlockHeaderui23Fastmm4.TBlockOperation]
41B996 [FastMM4][DebugGetMem$qqri]
41BD1F [FastMM4][DebugReallocMem$qqrrpvi]
40615D [System.pas][System][@ReallocMem$qqrrpvi][3524]
40CF62 [System.pas][System][@UStrSetLength$qqrr20System.UnicodeStringi][24163]
40D057 [System.pas][System][@UStrCat$qqrr20System.UnicodeStringrx20System.UnicodeString][24290]
8127D6 [LogHandler.pas][LogHandler][AddCustomLog$qqruiuii][160]
...

コードは非常にシンプルで、いくつかのプロジェクトでエラーなしで使用されました

procedure AddCustomLog(p1, p2: NativeUInt; MsgType: integer);
const
  MSG_LEN = 200;
var
  ErrorString: array [0 .. MSG_LEN] of Char;
  i: integer;
  temp: string;
  descr: UTF8String;
  b: byte;
  pb: PByte;
begin
  case MsgType of
    ...
    BUFFER_LOG: begin
        temp := 'len = ' + IntToStr(p2) + ' buf : ' + sLineBreak;
        descr := '';
        pb := PByte(p1);

        for i := 0 to p2 - 1 do begin
          b := pb^;
          // if i = 27 then LogAllocatedBlocksToFile(0, 0);
          temp := temp + format('%.2X ', [b]); //IntToHex(b, 2) + ' ';
          if ((b >= $20) and (b < $80)) or (b >= $C0) then
              descr := descr + UTF8Encode(AnsiChar(b))
          else
              descr := descr + '.';

          if (i mod $10) = $F then begin
            temp := temp + '  |  ' + UTF8ToString(descr) + sLineBreak;
            descr := '';
          end;
          inc(pb);
        end;

        if length(temp) > 0 then
            AddToLog(temp + '  |  ' + UTF8ToString(descr));
      end;
  end;
end;

FastMM は、 または で「メモリ不足」例外を発生させtemp := temp + format('%.2X ', [b]);ます。コール スタックは、_UStrCat、_UStrSetLength、_ReallocMem につながります。常に. パラメータのパラメータは、41 バイトで埋められた 128 バイト長の TBytes 配列のアドレスです ( NativeUInt(@FData[0]) )。メモリ アクセス ブレークポイントを 7FFFFE62540 に配置しようとしました (FastMM メッセージ「ポインタ アドレス 7FFFFE62540 で始まる 256 バイトの現在のメモリ ダンプのアドレス」) に、アプリケーションの開始からこのメモリ ブロックをトレースしました。アドレス 7FFFFE62450 とアドレス 7FFFFE62540 は、FastMM によって ptr + f0 として埋められます ( の場合)。このブロックのコントロール サムをチェックした後、FastMM が失敗します (CPU ウィンドウでトレース)。また、このログ部分を除外しようとしましたが、シンプルで同様の例外が発生しましたformatIntToHexi = 27p1i = 27inheritedオブジェクトの 1 つを作成します (このコードの実行後)。の下でのみ発生しFullDebugModeます。

最後に、同じオプションとFastMM4Options.inc32 ビットでこのプロジェクトをビルドしてチェックしようとしTarget Platformsましたが、エラーはまったくありません。すべて順調。ただし、Windows 7-64 ではデ​​バッグできません。

FastMM にコードのエラーや既知のバグはありますか? 私はそれを追跡するのに 3 日間費やしましたが、他に何をすべきかわかりません (スロットの最初の 4 GB メモリ、4 x 2048 を交換しようとさえしました)。FastMM4 の FastMM_FullDebugMode64.dll と FastMM_FullDebugMode.dll を使用しました。ありがとう。

編集:そのようなことを解決するのはひどいですが、私は自分で戦略を見つけたようです(解決、all in oneOLEまたはDirectモードに応じて異なるクラスと同じオブジェクト、異なるクラスオブジェクトとしてオブジェクトを使用することによって引き起こされるエラーの欠点でした)
1.置くエラーが発生する直前の LogAllocatedBlocksToFile(0, 0) への FastMM4 呼び出し
2. ログで最も近いオブジェクトを見つけます。私にとっては、エラー アドレスの 300 バイト下の $300 バイト近くのアドレスでオブジェクトでした
3. エラー アドレスの近くのゼロ以外の領域にデータ ブレークポイントを配置します (私にとっては) 40 バイト近く下にありました)。256 バイトのような大きな領域が変更によってトリガーされなかったため、いくつかのブレークポイント。この場合、最も近いオブジェクトの末尾 (アドレス + ログによるサイズ) とエラーのアドレスの間の領域でした。
4. ブレークポイントでコードを分析します。
5.何を追跡するかを見つけるために数回実行し、最終的にエラーコードの位置を取得しました。IDE はデータ ブレークポイントを無効にするため、実行ごとにデータ ブレークポイントを再度有効にします。

4

2 に答える 2

5

あなたが説明する症状は、ヒープの破損の症状です。ここでエラーが発生すると言います:

temp := temp + format('%.2X ', [b]);

tempとはどちらbもローカル変数であり、Format正しく動作することが知られています。したがって、私が考える唯一の結論は、このコードが実行される前にヒープが破損しているということです。

FastMM を見るのをやめて、コードに集中してください。簡単な SSCCE を作成し、そこから解決できない場合は、解決できるはずです。

于 2014-03-12T19:12:03.857 に答える
4

FastMM4 を使用している場合は、FastMM4.FullDebugModeScanMemoryPoolBeforeEveryOperation := true; すべてのメモリ操作の前に完全な破損チェックを実行するように設定してみてください。これにより処理速度が大幅に低下しますが、どこで問題が発生したかを簡単に見つけることができます。エラーが報告された場合、最後のメモリ操作と現在のコードの間のどこかで、何かが破損しています。これにより、検索がはるかに簡単になります。

于 2014-03-12T20:01:28.253 に答える