【问题标题】:Reading TValue from TRttiProperty fails (Property Type: set of Byte)从 TRttiProperty 读取 TValue 失败(属性类型:字节集)
【发布时间】:2015-03-16 22:03:27
【问题描述】:

我为 Byte 集合定义了一个类型、一个接口和一个实现该接口的类。 该接口具有 TTestSetofByte + getter 和 setter 类型的属性。没什么特别的。

type
 TTestSetOfByte = set of Byte;
  ITestInterface = interface
    ['{BCF0CEC2-F999-4E8A-A732-416F343C1629}']
    function GetPropSetOfByte: TTestSetOfByte;
    procedure SetPropSetOfByte(const Value: TTestSetOfByte);
    property PropSetOfByte: TTestSetOfByte read GetPropSetOfByte write SetPropSetOfByte;
  end;

  TTestClass3 = class(TInterfacedObject, ITestInterface)
  private
    FSetOfByte: TTestSetOfByte;
    function GetPropSetOfByte: TTestSetOfByte;
    procedure SetPropSetOfByte(const Value: TTestSetOfByte);
  public
    constructor Create;
    property PropSetOfByte: TTestSetOfByte read GetPropSetOfByte write SetPropSetOfByte;
  end;

问题是,当我尝试读取 PropSetOfByte 属性的值时,delphi 会抛出 EAccessViolation,我不明白为什么。其他类型(int, string) 的属性工作得很好。

这里是测试代码:

procedure TTestUtlRttiComparer.DeleteMe;
var
  i: Integer;
  Instance1: ITestInterface;
  Object1: TObject;
  RttiContext: TRttiContext;
  RttiProp: TRttiProperty;
  RttiValue1: TValue;
  Type1: TRttiType;
begin
  Instance1 := TTestClass3.Create;
  Check(Instance1.PropSetOfByte = [1,4], 'Making sure getter works!');
  Instance1.PropSetOfByte := [3,4];
  Check(Instance1.PropSetOfByte = [3,4], 'Making sure setter works!');

  Object1 := (Instance1 as TObject);
  Check(Assigned(Object1));

  RttiContext := TRttiContext.Create;
  try
    Type1 := RttiContext.GetType(Object1.ClassInfo);

    // Properties pruefen
    for i := 0 to High(Type1.GetProperties) do
    begin
      RttiProp :=  Type1.GetProperties[i];
      if RttiProp.Name = 'PropSetOfByte' then
      begin
        RttiValue1 := RttiProp.GetValue(Object1); // THIS CHECK FAILS with EACESSVIOLATION!!!
      end;
    end;
  finally
    RttiContext.Free;
  end;
end;

我正在使用 XE-2。

谢谢!

【问题讨论】:

  • 编译器是否为集合类型的属性生成RTTI?
  • @DavidHeffernan:是的,确实如此。

标签: delphi delphi-xe2 rtti


【解决方案1】:

TRttiType.GetValue()(更具体地说,System.Rtti 单元中的Invoke() 函数)尝试调用TTestClass3.GetPropSetOfByte() 时,它会崩溃。传入了正确的Self 指针,但Result 参数为nil,因此当GetPropSetOfByte() 尝试将FSetOfByte 分配给Result 时会发生崩溃。

简而言之,RTTI 系统没有为基于Set 的属性正确设置调用堆栈。我已经在 XE2、XE6 和 XE7 中重现了崩溃,并向 Embarcadero 提交了错误报告:

TRttiProperty.GetValue() 在基于 Set 的属性上崩溃 https://quality.embarcadero.com/browse/RSP-10206

【讨论】:

  • 感谢您的调查。阅读您的答案,您似乎自己调试了这个。你用的是哪个 Delphi 编译器?希望这在以后的版本中得到修复。您能想出任何解决方法来获得 TValue 吗?
  • 我使用 XE2 对其进行了调试,因为这是您使用的版本。我会用一些更高的版本来测试它,看看是否仍然会出现同样的问题。
  • 在 XE6 中仍然崩溃。我的 XE7 虚拟机现在不工作,所以我无法检查 XE7 是否也崩溃了。
  • 我终于能够在 XE7 中对其进行测试 - 它仍然崩溃。所以我已经为你提交了一个错误报告:quality.embarcadero.com/browse/RSP-10206
  • Rtti 中对大于 4 个字节的集合的完整处理似乎被破坏了 - 请参阅我在问题中的评论。
猜你喜欢
  • 2020-01-01
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
  • 2021-01-11
相关资源
最近更新 更多