TList <t>中的Delphi XE8错误,需要解决方法

时间:2015-04-27 21:58:42

标签: delphi generics tlist delphi-xe8

升级到XE8后,我们的一些项目开始破坏数据。看起来像TList实现中的一个错误。

program XE8Bug1;
{$APPTYPE CONSOLE}

uses
  System.SysUtils, Generics.Collections;

type
  TRecord = record
    A: Integer;
    B: Int64;
  end;

var
  FRecord: TRecord;
  FList: TList<TRecord>;

begin
  FList := TList<TRecord>.Create;
  FRecord.A := 1;
  FList.Insert(0, FRecord);
  FRecord.A := 3;
  FList.Insert(1, FRecord);
  FRecord.A := 2;
  FList.Insert(1, FRecord);
  Writeln(IntToStr(FList[0].A) + IntToStr(FList[1].A) + IntToStr(FList[2].A));

end.

此代码在XE7和之前(应该是)打印“123”,但在XE8中打印“120”。 也许有人知道这个的快速修补程序?

更新:非正式修复here

1 个答案:

答案 0 :(得分:32)

我发现现在TList<T>.Insert方法调用TListHelper.InternalInsertX取决于数据大小,在我的情况下:

procedure TListHelper.InternalInsertN(AIndex: Integer; const Value);
var
  ElemSize: Integer;
begin
  CheckInsertRange(AIndex);

  InternalGrowCheck(FCount + 1);
  ElemSize := ElSize;
  if AIndex <> FCount then
    Move(PByte(FItems^)[AIndex * ElemSize], PByte(FItems^)[(AIndex * ElemSize) + 1], (FCount - AIndex) * ElemSize);
  Move(Value, PByte(FItems^)[AIndex * ElemSize], ElemSize);
  Inc(FCount);
  FNotify(Value, cnAdded);
end;

我在第一次Move电话中看到了问题。目的地应该是:

PByte(FItems^)[(AIndex + 1) * ElemSize]

不是

PByte(FItems^)[(AIndex * ElemSize) + 1]

Aaargh!

最后,我在我的项目中使用了Delphi XE7中的System.Generics.Defaults.pas和System.Generics.Collections.pas单元,现在一切都按预期工作。

更新:正如我所见,RTL没有受到影响,因为它没有使用TList<T>.Insert来表示T和SizeOf&gt; 8(或者我想念一些东西?)

相关问题