访问冲突包含记录指针的RTTI转储记录

时间:2015-04-04 08:33:19

标签: delphi pointers record dump rtti

uses RTTI;

type TMyRecord = packed record
  name : String[20];
  age  : Integer;
end;

type TMasterCtrl = packed record
  MyRecord: ^TMyRecord;  // Error can be avoided by changing to `MyRecord: Pointer;`
end;

procedure RTTIDump(Instance, ATypeInfo: Pointer; Memo: TStrings; NameWidth, FieldTypeWidth, ValueWidth: Integer; PaddingChar: Char);
var
  rType: TRTTIType;
  fields: TArray<TRttiField>;
  i: Integer;
begin
  rType := TRTTIContext.Create.GetType(ATypeInfo);
  Memo.Add(rType.ToString);
  fields := rType.GetFields;
  for i := 0 to High(fields) do
    Memo.Add(Format('%s: %s :: %s', [
      fields[i].Name.PadRight(NameWidth, PaddingChar),
      fields[i].FieldType.ToString.PadRight(FieldTypeWidth, PaddingChar),
      fields[i].GetValue(Instance).ToString.PadRight(FieldTypeWidth, PaddingChar) ]));
end;

procedure TForm3.Button2Click(Sender: TObject);
var
  myRecord    : TMyRecord;
  MasterCtrl: TMasterCtrl;
begin
myRecord.name := 'Fred Bloggs';
myRecord.age  := 23;

MasterCtrl.MyRecord := @myRecord;

RTTIDump(Addr(MasterCtrl), TypeInfo(TMasterCtrl), Memo1.Lines, 18, 18, 0, ' ');
end;

如何修复此代码将创建的访问冲突,仍然使用指针记录?

2 个答案:

答案 0 :(得分:4)

您需要为指针使用正确的类型声明。

type
  PMyRecord =^TMyRecord;
  TMyRecord = packed record
  name : String[20];
  age  : Integer;
end;

type TMasterCtrl = packed record
  MyRecord: PMyRecord;  
end;

答案 1 :(得分:1)

正如LU RD所说,你必须为TMyRecord声明一个正确的指针类型,以便为TMasterCtrl.MyRecord字段生成正确的RTTI,否则field[s].FieldType属性会崩溃,因为没有输入信息进行检索。

type
  PMyRecord = ^TMyRecord; // <-- here
  TMyRecord = packed record
    name : String[20];
    age  : Integer;
  end;

  TMasterCtrl = packed record
    MyRecord: PMyRecord;  
  end;

话虽如此,您的代码还有另外两个问题:

  1. fields[i].GetValue(@Instance)

    Instance已包含TMasterCtrl实例的地址。使用@,您将错误的地址传递给GetValue()。您需要删除@

    fields[i].GetValue(Instance)
    
  2. 请勿致电rType.FreeTRttiContext拥有它并将为您释放它。