首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FastMM 64位“块头已损坏”

FastMM 64位“块头已损坏”
EN

Stack Overflow用户
提问于 2014-03-12 19:01:20
回答 2查看 802关注 0票数 2

最新的FastMM4 4.991,XE2,试图解决内存泄漏,并在FullDebugMode + LogErrorsToFile设置下得到了这个错误。错误

代码语言:javascript
复制
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]
...

代码非常简单,并在几个项目中使用,没有任何错误。

代码语言:javascript
复制
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]);中用formatIntToHex引发“内存不足”异常。调用堆栈导致_UStrCat、_UStrSetLength、_ReallocMem。总是在i = 27p1的参数是TBytes数组的地址,长度为128个字节,填充41个字节( NativeUInt(@FData) )。我尝试将内存访问断点放置到7FFFFE62540 (来自FastMM消息的地址“从指针地址7FFFFE62540开始的256个字节的当前内存转储”),从应用程序开始跟踪这个内存块:它是空的未使用区域,直到地址7FFFFE62450和地址7FFFFE62540被FastMM (i = 27时)填充为ptr + f0。检查此块以确定控制和后,FastMM失败(在CPU窗口中跟踪)。此外,我试图排除这个日志部分,但在简单的inherited创建对象(在执行代码后很远)获得了类似的异常。也只有在FullDebugMode下才会发生。

最后,我尝试用相同的选项和32位FastMM4Options.inc下的Target Platforms构建和检查这个项目--根本没有错误。百事大吉。但我不能在Windows 7-64下调试它。

那么,FastMM中是否存在代码错误或已知的错误呢?我花了3天的时间追踪它,没有其他的想法做什么(甚至试图替换前4GB内存插槽,4x2048)。使用FastMM_FullDebugMode64.dll和来自FastMM4的FastMM_FullDebugMode.dll。谢谢。

编辑:解决这些问题很糟糕,但我似乎为自己找到了策略(解决了all in one的缺点,根据OLE或直接模式,同一对象与不同的类相同,使用对象作为不同的类对象所造成的错误)

  1. 在错误发生之前将FastMM4调用放到LogAllocatedBlocksToFile(0,0)上
  2. 在日志中查找最近的对象,对我来说,它是一个比错误地址低300个字节的对象
  3. 将数据断点放置到错误地址附近的非零区域(对我来说,它在40字节以下)。几个断点,因为像256个字节这样的大区域不是由更改触发的。在这种情况下,它是最近的对象的结束(地址+按日志大小)和错误地址之间的区域。
  4. 分析断点上的代码。
  5. 几次运行,以找到什么要跟踪,并最终得到错误代码的位置。在每次运行时重新启用数据断点,因为IDE禁用它们。
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-12 19:12:03

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

代码语言:javascript
复制
temp := temp + format('%.2X ', [b]);

好的,tempb都是局部变量,而Format是正确工作的。因此,我要考虑的唯一结论是,在运行此代码之前,堆已经损坏。

停止查看FastMM,专注于您的代码。做一个简单的SSCCE,如果你不能从那里解决它,我们应该能够。

票数 5
EN

Stack Overflow用户

发布于 2014-03-12 20:01:28

如果您正在使用FastMM4,请尝试在每次内存操作之前设置FastMM4.FullDebugModeScanMemoryPoolBeforeEveryOperation := true; --它将运行一个完整的损坏检查。这可以让事情慢下来,但它也使我们更容易找到出问题的地方:当它报告一个错误时,然后在最后一个内存操作和当前代码之间的某个地方,一些东西被破坏了。这样你的搜索就容易多了。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22361339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档