- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的 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/
我正在编写一个 JS 程序,我有一个条件可以根据输入进行一些算术运算。如果我遇到操作类型为“add”,我需要将两个值相加;如果我得到“times”作为我的运算符值,我需要相乘。 我尝试使用基本的 if
我正在编写一个仅作为查看器的应用程序 - 无需创建、无需编辑、无需保存。 显然,那么,不会有自动保存,但是还有什么其他东西可以从 autosavesInPlace 返回 YES 改变世界,从而对观看者
Azure 开始出现以下错误: Unsupported token. Unable to initialize the authorization context. 每当我尝试更改我的应用程序时,我都
当我编写 out.println() 时,Eclipse 提示 out 无法解析。 我导入了 java.io.* 和其他 servlet 包。 最佳答案 只是在黑暗中拍摄,我认为这就是您正在寻找的出路
Azure 开始出现以下错误: Unsupported token. Unable to initialize the authorization context. 每当我尝试更改我的应用程序时,我都
是否可以执行类似的操作来检查 radio 表单是否未选中: if !($(this).find("input:checked")) {} 正确的语法是什么? 最佳答案 试试这个: $(this).fi
我正在尝试从表中选择行,其中 date 列值等于澳大利亚悉尼的当前日期 (UTC+10h)。服务器位于悉尼,因此我想使用 SYSDATETIME()。这是我的查询: SELECT * FROM dat
我听说 JavaScript 实际上并不像其他语言那样“指向”内存中的值(或对象,因为在 JS 中一切都是对象)。相反,JS 变量引用内存中的其他值/对象。这是真的?指向和引用之间的语义区别是什么?
我的计算机科学类(class)有一项作业,其中要求读取包含多个测试分数的文件,并要求我对它们进行求和并求平均值。虽然求和和求平均值很容易,但我在读取文件时遇到问题。老师说用这个语法 Scanner s
Java 的 XML 解析器似乎认为我的 XML 文档在根元素之后的格式不正确。但我已经用几种工具验证了它,但他们都不同意。这可能是我的代码错误,而不是文档本身的错误。如果你们能给我提供任何帮助,我将
根据这份文件: http://www.stroustrup.com/terminology.pdf l 值具有同一性且不可移动。 公关值是可移动的,但没有身份。 x 值具有同一性并且是可移动的。 关于
这个问题在这里已经有了答案: What does "atomic" mean in programming? (7 个答案) 关闭 5 年前。 我正在阅读 MongoDB 的 documentati
在 PHP 和 MySQL 中有没有一种方法能够比较 2 个不同的数组(列表)变量并说出有多少项是相同的 例如, $array1 = "hello, bye, google, laptop, yes"
本文来自 Effective Java Programs that use the int enum pattern are brittle. Because int enums are compil
C++ 中有一些特性是类型安全的,而另一些则不是。 C++ 类型安全示例: char c = 'a'; int *p = &c; // this is not allowed (compiler
我有一个 CS 课的作业,它说要读取一个包含多个测试分数的文件,并要求我对它们求和并取平均值。虽然求和和平均很容易,但我在读取文件时遇到了问题。老师说要用这个语法 Scanner scores = n
嗯.. 有时,PyDev 会说“ Unresolved 导入错误”。 在我的环境中 Python2.6.6 Eclipse3.7 PyDev2.2.2 错误是。 > Unresolved import
我正在向服务器发送请求,服务器正在处理请求并做出响应。但是在我的应用程序中,我收到了: Error Domain=NSURLErrorDomain Code=-1017 "cannot parse r
在我最近的一次讨论中,有人告诉我这样说是不正确的,因为 Ajax 已经是 Javascript。 上下文: “我如何在网页中 blablababal,这样它就不必刷新页面” 我的回答: “使用 Jav
下午好。 我一直在尝试使用 ffmpeg 将 .mpeg 拆分为一系列 .jpeg 图像。请注意,这是指定 here 的逆问题,但我面临的问题与该线程的作者面临的问题不同。 具体来说,我已经在我的 f
我是一名优秀的程序员,十分优秀!