我有这个简单的代码
procedure TForm2.btn1Click(Sender: TObject);
var s : TStringList;
function compare(s : TStringList; i1, i2 : integer) : integer;
begin
result := CompareText(s[i1], s[i2]);
end;
begin
s := TStringList.Create;
try
s.add('s1');
s.add('s2');
s.add('s3');
s.CustomSort(@compare);
finally
s.free;
end;
end;
当我将其编译为32位时,它按预期工作,但在使用64位时我得到访问冲突。
对于函数比较中的64位版本,s = nil. i2 = some random value
;
如果我在compare
函数之外提取btn1Click
函数,它也可以按预期工作,即使对于Win64目标也是如此。
是System.Classes的错误,有什么方法可以修复吗?
答案 0 :(得分:4)
本地嵌套函数不应该分配给过程变量(特别是不应该作为过程变量参数传递)。
http://docwiki.embarcadero.com/RADStudio/XE4/en/Procedural_Types - 搜索“嵌套”。
原因很简单:本地函数应该安排它们的堆栈,以便它们可以访问所有上层函数(父项)堆栈帧。然而,当这些函数被跳入而没有事先调用其父函数的所有链时,这些堆栈帧就不存在。而那种“突然出现”的潜水正是将他们的地址传递给那些不知道这个特定呼叫链的高管的情况。这就像调用一些对象的虚方法而没有VMT链接到父类而没有Self指向正确的VMT。
错误不是这样的代码在win64中不起作用。
错误在于它甚至可以在win32或win64中编译。
当Delphi修复bug时,除非你使compare
成为一个适当的全局函数,否则不会编译这样的代码。