升级到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这个?
更新:非官方修订是here
解决方法
我发现现在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。为SizeOf&T插入T。 8(或者我可能错过了什么?)