我发现 Delphi 5 在特定情况下会生成无效的汇编代码。我不明白一般情况下是什么情况。下面的示例会产生访问冲突,因为发生了非常奇怪的优化。对于记录或数组中的一个字节,Delphi 生成 push dword [...], pop ebx, mov .., bl 如果在此字节之后有数据(我们至少需要三个才能正确推送 dword),则可以正常工作,但失败如果数据不可访问。我在这里用 win32 Virtual* 函数模拟了严格的界限
特别是在 FeedBytesToClass 过程中访问的块的最后一个字节时发生错误。如果我尝试更改诸如使用数据数组而不是删除 actionFlag 变量的对象属性之类的东西,Delphi 会生成正确的汇编指令。
const
BlockSize = 4096;
type
TSomeClass = class
private
fBytes: PByteArray;
public
property Bytes: PByteArray read fBytes;
constructor Create;
destructor Destroy;override;
end;
constructor TSomeClass.Create;
begin
inherited Create;
GetMem(fBytes, BlockSize);
end;
destructor TSomeClass.Destroy;
begin
FreeMem(fBytes);
inherited;
end;
procedure FeedBytesToClass(SrcDataBytes: PByteArray; Count: integer);
var
j: integer;
Ofs: integer;
actionFlag: boolean;
AClass: TSomeClass;
begin
AClass:=TSomeClass.Create;
try
actionFlag:=true;
for j:=0 to Count-1 do
begin
Ofs:=j;
if actionFlag then
begin
AClass.Bytes[Ofs]:=SrcDataBytes[j];
end;
end;
finally
AClass.Free;
end;
end;
procedure TForm31.Button1Click(Sender: TObject);
var
SrcDataBytes: PByteArray;
begin
SrcDataBytes:=VirtualAlloc(Nil, BlockSize, MEM_COMMIT, PAGE_READWRITE);
try
if VirtualLock(SrcDataBytes, BlockSize) then
try
FeedBytesToClass(SrcDataBytes, BlockSize);
finally
VirtualUnLock(SrcDataBytes, BlockSize);
end;
finally
VirtualFree(SrcDataBytes, MEM_DECOMMIT, BlockSize);
end;
end;
最初,当我使用访问位图位的 RGB 数据时发生错误,但那里的代码太复杂,所以我将其缩小到这个片段。
所以问题是这里有什么特别的东西让Delphi产生push、pop、mov优化。我需要知道这一点,以便在一般情况下避免这种副作用。