代码之家  ›  专栏  ›  技术社区  ›  René Hoffmann esd

DynArraySize()只能在649个整数元素的数组中正常工作

  •  3
  • René Hoffmann esd  · 技术社区  · 7 年前

    Delphi 10.2更新2 并且能够追踪到更少的代码量(见下文)。

    我有一些 TPersistent -后代阶级 TMyObj 发布类型的属性的 TArray<Integer> . 当我通过 GetDynArrayProp() 并通过 DynArraySize()

    TDictionary<Integer,Boolean> Keys 拥有自己的财产 ToArray 我也试着修改 TMyObj.GetDynArray 从而返回 焦油<整数> 直接和正确的工作。

    动态分析()

    program RTTIPropDynArray;
    
    {$APPTYPE CONSOLE}
    
    uses
      System.Classes, System.Generics.Collections, System.SysUtils, System.TypInfo;
    
    type
      TMyDict  = TDictionary<Integer,Boolean>;
      TMyArray = TArray<Integer>;
    
      TMyObj = class(TPersistent)
      private
        FValues: TMyDict;
        function GetDynArray: TMyArray;
      public
        constructor Create(const ACount: Integer);
        destructor Destroy; override;
      published
        property DynArray: TMyArray read GetDynArray;
      end;
    
    { TMyObj }
    
    constructor TMyObj.Create(const ACount: Integer);
    begin
      FValues := TMyDict.Create;
      while FValues.Count < ACount do
        FValues.AddOrSetValue(Random(MaxInt), False);
    end;
    
    destructor TMyObj.Destroy;
    begin
      FreeAndNil(FValues);
      inherited;
    end;
    
    function TMyObj.GetDynArray: TMyArray;
    begin
      Result := FValues.Keys.ToArray;
    end;
    
    function Test(const ACount: Integer): Boolean;
    var
      LInstance: TMyObj;
      LExpectedSize: Integer;
      LDynArraySize: Integer;
    begin
      LInstance := TMyObj.Create(ACount);
      try
        LExpectedSize := Length(LInstance.DynArray);
        LDynArraySize := DynArraySize(GetDynArrayProp(LInstance, 'DynArray'));
        Result := LExpectedSize = LDynArraySize;
        if not Result then
          WriteLn(Format('Expected size: %d; DynArraySize: %d', [LExpectedSize, LDynArraySize]));
      finally
        LInstance.Free;
      end;
    end;
    
    var
      LCount: Integer;
    begin
      Randomize;
      LCount := 1;
      while Test(LCount) do
        Inc(LCount);
      ReadLn;
    end.
    
    1 回复  |  直到 7 年前
        1
  •  8
  •   Stefan Glienke    7 年前

    简而言之:你的密码坏了

    TEnumerable<T>.ToArrayImpl System.Generics.Collections.pas )在本书的结语中,这一点正在讨论中 System.TypInfo.GetDynArrayProp @DynArrayClear ). 由于没有对该数组的其他引用,因此会释放其内存(如果您进入 System.pas _FreeMem ). 这意味着对这个函数的每次调用都会返回一个悬空指针!

    有两种可能的解决方案不需要重写getter:

    • 使用来自的RTTI System.Rtti.pas 作为 TValue
    • 写你自己的版本 GetDynArrayProp