在TList <T>中的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”。 也许有人知道这个quickfix?
更新:非官方修复在这里
我发现现在的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
SizeOf> 8的T(或者我错过了某些东西?)