我设法将此问题减少到:
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.
从嵌套方法中访问时,captureString变量在这里被破坏. Win32编译引发EIntOverflow,Win64编译写出一个(损坏的)空字符串 – 可以通过某种操作将构建引入AV或其他异常,但在所有情况下,在进入嵌套过程时对本地变量的引用都会被破坏.
这似乎只有在闭包中捕获captureString时才会发生.
出了什么问题?
解决方法
这似乎是一个编译器错误:
#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;