Delphi 5は、特定の場合に無効なアセンブリコードを生成することがわかりました。一般的にどのような場合かわかりません。以下の例では、非常に奇妙な最適化が発生するため、アクセス違反が発生します。レコードまたは配列のバイトに対して、Delphiはプッシュdword [...]、pop ebx、mov ..、blを生成します。このバイトの後にデータがある場合は正しく機能しますが(dwordを正しくプッシュするには少なくとも3つ必要です)、失敗します。データにアクセスできない場合。ここでは、win32Virtual*関数を使用して厳密な境界をエミュレートしました
具体的には、FeedBytesToClassプロシージャ内でアクセスされたブロックの最後のバイトでエラーが発生します。そして、remove 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がプッシュ、ポップ、ムーブの最適化を生成するように、ここで何が非常に具体的であるかということです。一般的にそのような副作用を避けるために私はこれを知る必要があります。