J..*_*... 8 delphi closures anonymous-function delphi-10-seattle
我已设法将此问题减少到此:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Threading;
procedure Foo(AString: string);
var
LTask : ITask;
capturedString : string;
procedure Nested;
begin
try
WriteLn('Nested : ' + capturedString); { ! EIntOverflow (Win32) here }
except on E : Exception do
WriteLn(E.Message);
end;
end;
begin
capturedString := AString;
WriteLn('Local : ' + capturedString);
Nested;
LTask := TTask.Create(
procedure
procedure AnonNested;
begin
WriteLn(capturedString); { Removing this eliminates the problem }
end;
begin
end);
end;
begin
Foo('foo');
ReadLn;
end.
Run Code Online (Sandbox Code Playgroud)
capturedString从嵌套方法中访问变量时,变量会被破坏.一个Win32编译加薪EIntOverflow,一个Win64的编译写出一个(腐败)空字符串-无论是构建可以挑起到AV或其他异常的一些操作,但是在所有情况下,参照本地变量进入时被破坏Nested的过程.
这似乎只有capturedString在闭包中捕获时才会发生.
出了什么问题?
这似乎是一个编译器错误,已在 10.2 中解决:
#RSP-18833:通过闭包捕获会破坏嵌套方法中使用的局部变量
解决方法是在匿名方法中使用第二个变量进行捕获:
procedure Foo(AString: string);
var
LTask : ITask;
capturedString, s2 : string;
procedure Nested;
begin
try
WriteLn('Nested : ' + capturedString);
except on E : Exception do
WriteLn(E.Message); { !!! }
end;
end;
begin
capturedString := AString;
s2 := capturedString;
WriteLn('Local : ' + capturedString);
Nested;
LTask := TTask.Create(
procedure
procedure AnonNested;
begin
WriteLn(s2); { Capture another variable }
end;
begin
end);
end;
Run Code Online (Sandbox Code Playgroud)