我有这个简单的代码
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
,即使对于Win64目标,它也能按预期工作。 btn1Click
之外的函数功能。
是否是System.Classes的bug,有什么办法修复吗?
最佳答案
局部嵌套函数不应该分配给过程变量(特别是不应该作为过程变量参数传递)。
http://docwiki.embarcadero.com/RADStudio/XE4/en/Procedural_Types - 搜索“嵌套”。
原因很简单:本地函数应该安排它们的堆栈,以便它们可以访问所有上层函数(父级)堆栈帧。然而,当这些函数在没有事先一一调用其父函数的所有链的情况下跳转到这些函数时,这些堆栈帧就不可能存在。当将他们的地址传递给不知道这个特定调用链的高管时,就会发生这种“突然”的跳水。这就像在没有 VMT 链接到父类并且没有 Self 指向正确的 VMT 的情况下调用某个对象的虚拟方法。
问题并不是这样的代码在 win64 中不起作用。
错误在于它甚至可以在 win32 或 win64 中编译。
当 Delphi 修复该错误时,它不会再编译这样的代码,除非您将 compare
设为适当的全局函数,就像它应该的那样。
关于delphi - 使用 Delphi XE3 64 位的嵌套比较器函数 TStringList.CustomSort 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17783302/