正しいと思われる Delphi コードの予期しないアクセス違反がいくつかありますが、コンパイルが間違っているようです。私はそれを減らすことができます
procedure Run(Proc: TProc);
begin
Proc;
end;
procedure Test;
begin
Run(
procedure
var
S: PChar;
procedure Nested;
begin
Run(
procedure
begin
end);
S := 'Hello, world!';
end;
begin
Run(
procedure
begin
S := 'Hello';
end);
Nested;
ShowMessage(S);
end);
end;
私に起こることは、それS := 'Hello, world!'
が間違った場所に保存されていることです。そのため、アクセス違反が発生するか、ShowMessage(S)
"Hello" が表示されます (場合によっては、匿名プロシージャの実装に使用されたオブジェクトを解放するときにアクセス違反が発生します)。
私は Delphi XE を使用しており、すべてのアップデートがインストールされています。
これがどこで問題を引き起こすかをどのように知ることができますか? 匿名の手続きを避けるためにコードを書き直す方法は知っていますが、どのような状況でそれらが間違ったコードにつながるかを正確に把握するのに苦労しているため、どこでそれらを避けるべきかわかりません。
これが Delphi の以降のバージョンで修正されているかどうかを知りたいのですが、興味深いだけでなく、現時点ではアップグレードはオプションではありません。
QC では、最新のレポートで同様の#91876を見つけることができますが、これは Delphi XE で解決されています。
更新:
AlexSC のコメントに基づいて、わずかに変更します。
...
procedure Nested;
begin
Run(
procedure
begin
S := S;
end);
S := 'Hello, world!';
end;
...
動作します。
生成されたマシンコード
S := 'Hello, world!';
失敗したプログラムでは
ScratchForm.pas.44: S := 'Hello, world!';
004BD971 B89CD94B00 mov eax,$004bd99c
004BD976 894524 mov [ebp+$24],eax
一方、正しいバージョンは
ScratchForm.pas.45: S := 'Hello, world!';
004BD981 B8B0D94B00 mov eax,$004bd9b0
004BD986 8B5508 mov edx,[ebp+$08]
004BD989 8B52FC mov edx,[edx-$04]
004BD98C 89420C mov [edx+$0c],eax
失敗したプログラムで生成されたコードはS
、コンパイラによって生成されたクラスに移動されたことを認識してい[ebp+$24]
ません。ネストされたメソッドの外部ローカル変数にアクセスする方法ローカル変数へのアクセス方法。