2

我有这个简单的代码

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 的错误,有什么办法可以修复吗?

4

1 回答 1

4

本地嵌套函数不应分配给过程变量(特别是不应作为过程变量参数传递)。

http://docwiki.embarcadero.com/RADStudio/XE4/en/Procedural_Types - 搜索“嵌套”。

原因很简单:本地函数应该安排它们的堆栈,以便它们可以访问所有上层函数(父级)堆栈帧。但是,当这些函数在没有事先调用其父函数的所有链的情况下跳转到这些函数时,这些堆栈帧将不存在。而这种“出乎意料”的潜水正是将他们的地址传递给不知道这个特定调用链的高管时发生的事情。这就像在没有 VMT 链接到父类并且没有 Self 指向正确 VMT 的情况下调用某些对象的虚拟方法。

错误不是这样的代码在win64中不起作用。

错误是它甚至可以在 win32 或 win64 中编译。

当 Delphi 修复这个错误时,它不会再编译这样的代码,除非你compare像它应该那样制作一个适当的全局函数。

于 2013-07-22T09:13:50.470 回答