Delphi XE8 ошибка в TList, нужно обходное решение
после обновления до 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.
этот код печатает " 123 "в XE7 и раньше (как и должно быть), но в XE8 он печатает"120". Может кто-то знает quickfix для этого?
обновление: неофициальное исправление здесь
1 ответов
я обнаружил, что теперь 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]
аааах
наконец, я использовал систему.Дженерик.По умолчанию.и системы ООПТ.Дженерик.Коллекции.pas единицы из Delphi XE7 в моих проектах, и теперь все работает так, как ожидалось.
обновление: как я вижу, RTL не влияет, как это не использовать TList<T>.Insert
для T с SizeOf > 8 (или, может быть, я что-то пропустил?)