2015-04-04 78 views
-2
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; 

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

+3

请不要发布随机代码,不要解释实际问题与它有什么关系,代码行失败,错误消息等。 – 2015-04-04 08:46:01

+0

好的。下一次,我会在第9行发表评论“在错误可以通过改变为'MyRecord:Pointer;'”来避免错误,“在如何解决此代码将创建的访问冲突之前,仍然使用指向记录的指针?快乐? – wittrup 2015-04-04 09:05:34

+0

我不明白你为什么使用短字符串,或为什么你打包你的记录 – 2015-04-04 09:53:55

回答

1

鲁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拥有它,并将为你释放它。

+0

3.在使用它之前,不检查'fields [i] .FieldType'是否被分配。 – 2015-04-04 10:07:04

+0

@NicholasRing:虽然,人们通常不会期望'FieldType'失败。这是RTTI世代中的一种侥幸,而不是检索。 – 2015-04-05 16:48:48

+0

它不是侥幸,而是RTTI世代中的一个错误,因此测试以确定它是否被分配是一种预防措施。 – 2015-04-07 10:16:36

4

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

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

type TMasterCtrl = packed record 
    MyRecord: PMyRecord; 
end;