我有一些我认为是正确的 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]
是如何访问嵌套方法的外部局部变量如何访问局部变量。