本文介绍了TList>中的Delphi XE8错误,需要解决方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 程序XE8Bug1; 
{$ APPTYPE CONSOLE}

使用
System.SysUtils,Genericics.Collections;

type
TRecord = record
A:整数;
B:Int64;
结束

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));

结束。

此代码在XE7和之前(应该是)打印123,但在XE8中打印120。
也许有人知道这个quickfix?



更新:非官方修复是

解决方案

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

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

InternalGrowCheck(FCount + 1);
ElemSize:= ElSize;
如果AIndex<> FCount然后
移动(PByte(FItems ^)[AIndex * ElemSize],PByte(FItems ^)[(AIndex * ElemSize)+ 1],(FCount - AIndex)* ElemSize);
Move(Value,PByte(FItems ^)[AIndex * ElemSize],ElemSize);
Inc(FCount);
FNotify(Value,cnAdded);
结束

我在第一个 Move 中看到问题呼叫。目的地应该是:

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

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

Aaargh!



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

$ b $更新:如我所见,RTL不受影响,因为它不使用 TList< T> .Insert for T with SizeOf> 8(或者可能我想念某些东西?)


After upgrading to XE8 some of our projects start to break data. Looks like a bug in TList realization.

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.

This code prints "123" in XE7 and before (as it should be), but in XE8 it prints "120".Maybe someone know a quickfix for this?

Update: unofficial fix is here

解决方案

I found that now the TList<T>.Insert method call TListHelper.InternalInsertX depends on the data size, in my case:

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;

I see the problem in the first Move call. Destination should be:

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

not

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

Aaargh!

Finally, I've used the System.Generics.Defaults.pas and System.Generics.Collections.pas units from Delphi XE7 in my projects, and now all works as expected.

Update: as I see, RTL not affected, as it isn't use TList<T>.Insert for T with SizeOf > 8 (or maybe I miss something?)

这篇关于TList&gt;中的Delphi XE8错误,需要解决方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-11 21:31