I've managed to reduce this problem to this :
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.
Here the capturedString
variable gets corrupted when accessed from within a nested method. A Win32 compile raises EIntOverflow
, a Win64 compile writes out a (corrupt) empty string - either build can be provoked into AV or other exceptions with some manipulation but in all cases the reference to the local variable is corrupted when entering the Nested
procedure.
This seems to only happen if capturedString
is captured in a closure.
What's going wrong?