快MM 64 位"The block header has been corrupted"



最新的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在具有formatIntToHextemp := temp + format('%.2X ', [b]);处引发"内存不足"异常。调用堆栈导致_UStrCat、_UStrSetLength和_ReallocMem。始终处于i = 27p1的参数是TB数组的地址,长度128字节,填充41字节(NativeUInt(@FData[0]((。我尝试将内存访问断点设置为7FFFFE62540(来自FastMM消息"从指针地址7FFFFE625 40开始的256字节的当前内存转储"的地址(,从应用程序启动开始跟踪此内存块:它是空的未使用区域,直到在地址7FFFFE62450创建内存块,地址7FFFFEM625 40由FastMM填充为ptr+f0(当i = 27时(。在检查此块的控制和后,FastMM失败(在CPU窗口中跟踪(。此外,我还试图排除这个日志部分,但在一个对象的简单inherited创建中(在执行该代码之后很久(也出现了类似的异常。也仅在FullDebugMode下发生。

最后,我尝试用相同的选项和32位Target Platforms下的FastMM4Options.inc来构建和检查这个项目——根本没有错误。一切都很好。除了我不能在Windows 7-64下调试它。

那么FastMM中是否存在代码错误或已知错误?我花了3天时间跟踪它,没有其他想法该怎么办(甚至试图更换插槽中的前4GB内存,4 x 2048(。已使用FastMM4中的FastMM_FullDebugMode64.dll和FastMM_FallDebugMode.dll。谢谢

edit:解决这样的问题很糟糕,但我似乎找到了自己的策略(解决了问题,是all in one的缺点,根据OLE或Direct模式将同一对象作为不同的类,将对象用作不同的类对象引起的错误(
1.在错误发生之前立即对LogAllocatedBlocksToFile(0,0(进行FastMM4调用
2.在日志中查找最近的对象,对我来说,这是一个地址比错误地址低300字节的对象
3.将数据断点放在错误地址附近的非零区域(对我来说,它在下面大约40美元字节(。几个断点,因为像256字节这样的大区域并没有被更改触发。在这种情况下,它是最近对象的末尾(地址+日志大小(和错误地址之间的区域
4.分析断点上的代码
5.多次运行以查找要跟踪的内容,最终得到错误代码位置。在每次运行时重新启用数据断点,因为IDE会禁用它们。

您描述的症状是堆损坏。你说错误发生在这里:

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

tempb都是局部变量,Format可以正常工作。因此,我想得出的唯一结论是,在这段代码运行之前,您已经损坏了堆。

别再看FastMM了,把注意力集中在你的代码上。做一个简单的SSCCE,如果你不能从那里解决它,我们应该能够。

如果您使用的是FastMM4,请尝试设置FastMM4.FullDebugModeScanMemoryPoolBeforeEveryOperation := true;它将在每次内存操作之前运行完全损坏检查。这确实会减慢速度,但也更容易发现哪里出了问题:当它报告错误时,在上一次内存操作和当前代码之间的某个地方,某个东西被损坏了。这使您的搜索更加容易。

相关内容

  • 没有找到相关文章

最新更新