加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

如何使用TList解决Delphi 10的错误?

发布时间:2020-12-15 04:01:28 所属栏目:大数据 来源:网络整理
导读:我偶然发现了Delphi 10 Seattle Update 1中的一个错误.让我们看看以下代码: procedure TForm1.Button1Click(Sender: TObject);begin//----------We crash here---------------- FList.Items[0] := SplitString('H:E',':');end;procedure TForm1.FormCreate(
我偶然发现了Delphi 10 Seattle Update 1中的一个错误.让我们看看以下代码:
procedure TForm1.Button1Click(Sender: TObject);
begin
//----------We crash here----------------
  FList.Items[0] := SplitString('H:E',':');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FList := TList<TStringDynArray>.Create;
  FList.Add(SplitString('H:E',':'));
  FList.Items[0] := SplitString('H:E',':');
end;

乍一看,似乎TList< T>没有正确管理它包含的动态数组的生命周期,但是再次,如果以64位编译它就可以正常工作,它只会崩溃32位(我明白这并不意味着64中不存在错误)位…).

请注意,使用了SplitString,因为if是第一个返回动态数组的函数. TList< TBookmark>遇到了原始问题.它表现出同样的问题.

有可能解决错误重写过程Button1Click,如下所示:

procedure TForm1.Button1Click(Sender: TObject);
var MyArray : TStringDynArray;
begin
  MyArray := FList.Items[0];
  FList.Items[0] := SplitString('H:E',':');
  //----------Yeah! We don't crash anymore!-----------
end;

但是绕过我修改它们以解决这个bug的所有应用程序并不是我的首选选项.如果可能的话,我更喜欢找到有问题的例程并在内存中修补它.

如果有人遇到这个问题并找到了解决方法,我将不胜感激.否则,如果我找到合适的解决方法,我会发布我的.

此外,如果问题仍然存在于柏林,请发表评论.

解决方法

毕竟,这个bug仍然存在于64位.它没有为TStringDynArray崩溃,但它确实为其他动态数组类型.

可以在Generics.Collections中的以下代码中找到问题的根源:

procedure TListHelper.DoSetItemDynArray(const Value; AIndex: Integer);
type
  PBytes = ^TBytes;
var
  OldItem: Pointer;
begin
  OldItem := nil;
  try
    CheckItemRangeInline(AIndex);

    TBytes(OldItem) := PBytes(FItems^)[AIndex];
    PBytes(FItems^)[AIndex] := TBytes(Value);

    FNotify(OldItem,cnRemoved);
    FNotify(Value,cnAdded);
  finally
    DynArrayClear(OldItem,FTypeInfo); //Bug is here.
  end;
end;

会发生什么,将错误的TypeInfo传递给DynArrayClear.在TList< TStringDynArray>的情况下,传递TypeInfo(TArray< TStringDynArray>)而不是TypeInfo(TStringDynArray).据我所知,正确的呼吁是:

DynArrayClear(OldItem,pDynArrayTypeInfo(NativeInt(FTypeInfo) + pDynArrayTypeInfo(FTypeInfo).Name).elType^);

私有程序使拦截变得复杂.我这样做是因为记录助手仍然可以访问Delphi 10中记录的私有部分.我想这对柏林的用户来说会更复杂.

function TMyHelper.GetDoSetItemDynArrayAddr: TDoSetItemDynArrayProc;
begin
  Result := Self.DoSetItemDynArray;
end;

希望Embarcadero有一天能解决这个问题……

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读