在嵌套方法中访问时被闭包捕获破坏的局部变量
Local variable broken by closure capture when accessed in nested method
我已经设法将这个问题简化为:
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.
这里的 capturedString
变量在从嵌套方法中访问时被破坏。一个 Win32 编译引发 EIntOverflow
,一个 Win64 编译写出一个(损坏的)空字符串 - 构建可以通过一些操作被激发到 AV 或其他异常,但在所有情况下,当进入Nested
程序。
这似乎只有在闭包中捕获 capturedString
时才会发生。
怎么了?
这似乎是 10.2 中已解决的编译器错误:
#RSP-18833: Capture by closure corrupts local variable used in nested method
解决方法是在匿名方法中使用第二个变量进行捕获:
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;
我已经设法将这个问题简化为:
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.
这里的 capturedString
变量在从嵌套方法中访问时被破坏。一个 Win32 编译引发 EIntOverflow
,一个 Win64 编译写出一个(损坏的)空字符串 - 构建可以通过一些操作被激发到 AV 或其他异常,但在所有情况下,当进入Nested
程序。
这似乎只有在闭包中捕获 capturedString
时才会发生。
怎么了?
这似乎是 10.2 中已解决的编译器错误:
#RSP-18833: Capture by closure corrupts local variable used in nested method
解决方法是在匿名方法中使用第二个变量进行捕获:
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;