What should I do or don't do to avoid Delphi "push dword" bug.
Posted
by Maksee
on Stack Overflow
See other posts from Stack Overflow
or by Maksee
Published on 2009-08-18T15:36:38Z
Indexed on
2010/03/20
2:11 UTC
Read the original article
Hit count: 488
I found that Delphi 5 generates invalid assembly code in specific cases. I can't understand in what cases in general. The example below produces access violation since a very strange optimization occurs. For a byte in a record or array Delphi generates push dword [...], pop ebx, mov .., bl that works correctly if there are data after this byte (we need at least three to push dword correctly), but fails if the data is inaccessible. I emulated the strict boundaries here with win32 Virtual* functions
Specifically the error occurs when the last byte from the block accessed inside FeedBytesToClass procedure. And if I try to change something like using data array instead of object property of remove actionFlag variable, Delphi generates correct assembly instructions.
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;
Initially the error occured when I used access to RGB data of bitmap bits, but the code there is too complex so I narrowed it to this fragment.
So the question is what is here so specific that makes Delphi produce push,pop,mov optimization. I need to know this in order to avoid such side effects in general.
© Stack Overflow or respective owner