23 delphi anonymous-methods delphi-xe
我对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;
Run Code Online (Sandbox Code Playgroud)
对我来说发生的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;
...
Run Code Online (Sandbox Code Playgroud)
确实有效.
生成的机器代码
S := 'Hello, world!';
Run Code Online (Sandbox Code Playgroud)
在失败的计划中
ScratchForm.pas.44: S := 'Hello, world!';
004BD971 B89CD94B00 mov eax,$004bd99c
004BD976 894524 mov [ebp+$24],eax
Run Code Online (Sandbox Code Playgroud)
而正确的版本是
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
Run Code Online (Sandbox Code Playgroud)
失败程序中生成的代码没有看到S已经移动到编译器生成的类,[ebp+$24]是如何访问嵌套方法的外部局部变量 如何访问局部变量.
我怎么知道这会在哪里引起问题?
目前还很难说。
如果我们了解 Delphi XE2 中修复的本质,我们就会处于更好的位置。
您所能做的就是避免使用匿名函数。
Delphi 已经有了过程变量,所以对匿名函数的需求并不是那么迫切。
请参阅http://www.deltics.co.nz/blog/posts/48。
我很想知道这个问题是否在 Delphi 的更高版本中得到修复
根据 @Sertac Akyuz 的说法,这个问题已在 XE2 中修复。
就我个人而言,我不喜欢匿名方法,并且不得不禁止人们在我的 Java 项目中使用它们,因为我们的代码库中有很大一部分是匿名的(事件处理程序)。
极端适度地使用我可以看到用例。
但在 Delphi 中,我们有过程变量和嵌套过程……没有那么多。