gpt4 book ai didi

delphi - FastMM4 说 "The block footer has been corrupted"

转载 作者:行者123 更新时间:2023-12-03 15:11:48 28 4
gpt4 key购买 nike

我的 Delphi 7 应用程序中有这个函数,它运行得很好,直到我将 FastMM4 v4.99 纳入项目中。一旦包含在内,FastMM4 就会发出以下错误消息:“FastMM 在 FreeMem 操作期间检测到错误。 block 页脚已损坏。”执行在 FreeMem 行停止。

function BinaryFieldToArrayOfWord( aBinaryField   : TVarBytesField;
out aArrValues : TArrWord ) : Boolean;
var
p : Pointer;
begin
if not aBinaryField.IsBlob then
begin
GetMem( p, aBinaryField.DataSize );
try
if aBinaryField.GetData( p ) then
begin
// do something
end;
finally
FreeMem( p, aBinaryField.DataSize );
end;
end; // if
end;

首先我认为函数中一定有错误,但它实际上与 Delphi 7 帮助中的 TField.GetData 方法示例相同:

{ Retrieve the "raw" data from Field1 }
with Field1 do
begin
if not IsBlob { this does not work for BLOB fields }
begin
{ Allocate space }
GetMem(MyBuffer, DataSize);
try
if not GetData(MyBuffer) then
MessageDlg(DisplayName + ' is NULL', mtInformation, [mbOK], 0)
else
{ Do something with the data };
finally
{ Free the space }
FreeMem(MyBuffer, DataSize);
end;
end;
end;

我在网上发现,出现上述错误信息往往是因为数据空间不足。因此,我增加了内存块的大小,错误消息消失了,函数按预期工作。经过一番实验,我发现需要 2 个字节就足够了:

    GetMem( p, aBinaryField.DataSize + 2 );

FreeMem( p, aBinaryField.DataSize + 2 );

虽然它解决了我的问题,但我对这个解决方案并没有完全放松,因为我不知道它的背景。很高兴知道此消息的原因。 FastMM4 是否需要额外的 2 个字节作为其自己的页脚?

更新:经过一天的调试后,我现在相信 Delphi 7 TField.GetData 方法中存在错误。它在分配的内存块之外写入 2 个零字节。我在使用和不使用 FastMM4 的情况下进行了尝试,并且在两种情况下都会覆盖(因此这不是 FastMM4 错误)。我还尝试将字段类型转换为 TVarBytesField,没有区别。这是我使用的代码,带有详细注释,包含结果。我唯一剩下的问题是:他们在后来的 Delphis 中纠正了这个错误吗?

  procedure TfrmMain_PBC_TH.btnDEBUGClick(Sender: TObject);
type
TArrBytes = array of Byte;
var
p : Pointer;
qryTest : TADOQuery;
begin
qryTest := TADOQuery.Create( Application );
try
// The type of the TQM_BinaryData.BinData column in the MSSQL database is a varbinary(7900).
// Load the #168 binary data record. It contains exactly 7900 bytes, and the value of each byte is 255
qryTest.Connection := MainConn;
qryTest.SQL.Add('SELECT [BinData] FROM [TQM_BinaryData] WHERE [Id] = 168');
qryTest.Open;

// Allocate the memory block for this.
GetMem( p, qryTest.FieldByName('BinData').DataSize );
// DataSize is 7902 because all TVarBytesFields have 2 byte prefix in Delphi, containing the data length.
// So the size of the allocated memory block is 7902 bytes - we are correct so far.
try
// Values of the first four bytes beyond the end of the memory block (memory thrash at this point) before GetData:
// TArrBytes(p)[7902] = 96
// TArrBytes(p)[7903] = 197
// TArrBytes(p)[7904] = 219
// TArrBytes(p)[7905] = 43

// Critical point: get the data from the field with the Delphi GetData method
qryTest.FieldByName('BinData').GetData( p );

// Values after GetData:
// TArrBytes(p)[0] = 220 TArrBytes(p)[0] and TArrBytes(p)[1] contains the length of the binary data
// TArrBytes(p)[1] = 30 it is correct as 30 * 256 + 220 = 7900
// TArrBytes(p)[2] = 255 actual data starts
// TArrBytes(p3[2] = 255
// ...
// TArrBytes(p)[7900] = 255
// TArrBytes(p)[7901] = 255 actual data ends
// TArrBytes(p)[7902] = 0 changed from 96!
// TArrBytes(p)[7903] = 0 changed from 197!
// TArrBytes(p)[7904] = 219 no change
// TArrBytes(p)[7905] = 43 no change
finally
// Here FastMM4 throws the block footer corrupt error because GetData modified the 2 bytes after the allocated memory block
FreeMem( p );
end;

qryTest.Close;
finally
qryTest.Free;
end;
end;

添加数据断点后,调用堆栈为:

    @FillChar(???,???,???)
TDataSet.DataConvert($7D599770,$12F448,$7D51F7F0,True)
VarToBuffer
TCustomADODataSet.GetFieldData($7D599770,$7D51F7F0,True)
TField.GetData($7D51F7F0,True)
TfrmMain_PBC_TH.btnDEBUGClick($7FF7A380)
TControl.Click
TButton.Click

最佳答案

FastMM 在您分配的 block 末尾分配一些内存,并在那里写入已知值。然后,当您解除分配时,FastMM 会检查这些值是否符合预期。如果不是,则会引发您看到的错误,因为 FastMM 知道您的代码写入超出了内存块的末尾。

因此,try/finally block 内的某些内容正在写入超出内存块末尾的内容。这就是为什么增加其大小可以消除 FastMM 错误。如果没有看到该代码,我们无法判断到底出了什么问题,您将需要进行一些调试来解决问题。

您对“解决方案”的担忧是完全正确的。反复试验从来都不是合理的编程方式。您必须找出程序写入超出 block 末尾的原因。

一种方法是为紧邻该 block 末尾的地址设置数据断点。这将迫使调试器中断写入超出 block 末尾的代码。

顺便说一句,您不需要将第二个参数传递给 FreeMem。这样做会让你的代码更难维护,而且毫无用处。仅将指针传递给 FreeMem。

关于delphi - FastMM4 说 "The block footer has been corrupted",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10329940/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com