最新的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]);
或format
在IntToHex
处引发“内存不足”异常。调用堆栈会导致_UStrCat,_UStrSetLength,_ReallocMem。始终在i = 27
。 p1
的参数是TBytes数组的地址128字节长度,填充41字节(NativeUInt(@FData [0]))。
我试图将内存访问断点设置为7FFFFE62540(来自FastMM消息的地址“从指针地址7FFFFE62540开始的256字节当前内存转储”),从应用程序启动跟踪此内存块:它是空的未使用区域,直到创建内存块地址7FFFFE62450和地址7FFFFE62540由FastMM填充为ptr + f0(当i = 27
时)。检查此块后,控制和FastMM失败(在CPU窗口中跟踪)。
此外,我试图排除这个日志部分,但在简单的inherited
创建一个对象(远在此代码执行之后)时得到了类似的异常。也只在FullDebugMode
下发生。
最后,我尝试使用相同的选项构建并检查此项目,并在32位FastMM4Options.inc
下Target Platforms
- 根本没有错误。一切都好。除非我无法在Windows 7-64下调试它。
那么FastMM中的代码或已知错误是否有错误?我花了3天跟踪它,没有其他想法做什么(甚至试图替换插槽中的前4 GB内存,4 x 2048)。使用来自FastMM4的FastMM_FullDebugMode64.dll和FastMM_FullDebugMode.dll。感谢。
编辑:解决这些问题很糟糕但似乎我找到了自己的策略(解决了,这是all in one
的缺点,同一个对象作为不同的类,取决于OLE或Direct模式,使用对象作为不同类对象引起的错误)
1.在发生错误之前,将FastMM4调用发送到LogAllocatedBlocksToFile(0,0)
2.在日志中查找最近的对象,对我而言,它是靠近错误地址的300字节附近的地址对象
3.将数据断点放到错误地址附近的非零区域(对我来说,它接近40美元以下)。几个断点,因为像256字节这样的大区域不会被更改触发。在这种情况下,它是最近对象的末尾(地址+按日志的大小)和错误的地址之间的区域
4.分析断点上的代码
5.几次运行以找到要跟踪的内容并最终获得错误代码位置。每次运行时重新启用数据断点,因为IDE会禁用它们。
答案 0 :(得分:5)
您描述的症状是堆损坏的症状。你说错误发生在这里:
temp := temp + format('%.2X ', [b]);
嗯,temp
和b
都是局部变量,并且已知Format
可以正常工作。因此,我要考虑的唯一结论是,在此代码运行之前,您已经损坏了堆。
停止查看FastMM并专注于您的代码。制作一个简单的SSCCE如果你不能从那里解决它,我们应该能够。
答案 1 :(得分:4)
如果您正在使用FastMM4,请尝试设置FastMM4.FullDebugModeScanMemoryPoolBeforeEveryOperation := true;
它将在每次内存操作之前运行完整的损坏检查。这确实可以减慢速度,但它也可以更容易地找到出错的地方:当它报告错误时,然后在最后一次内存操作和当前代码之间的某个位置,某些东西被破坏了。这使您的搜索更容易。