包含记录指针的访问冲突 RTTI 转储记录
Access violation RTTI dumping record containing record pointers
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;
如何解决此代码将创建的访问冲突,仍然使用指向记录的指针?
您需要为指针使用正确的类型声明。
type
PMyRecord =^TMyRecord;
TMyRecord = packed record
name : String[20];
age : Integer;
end;
type TMasterCtrl = packed record
MyRecord: PMyRecord;
end;
正如 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;
也就是说,您的代码还有另外两个问题:
fields[i].GetValue(@Instance)
Instance
已经包含 TMasterCtrl
实例的地址。通过使用 @
,您将错误的地址传递给 GetValue()
。您需要删除 @
:
fields[i].GetValue(Instance)
不叫rType.Free
。 TRttiContext
拥有它并将免费为您提供。
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;
如何解决此代码将创建的访问冲突,仍然使用指向记录的指针?
您需要为指针使用正确的类型声明。
type
PMyRecord =^TMyRecord;
TMyRecord = packed record
name : String[20];
age : Integer;
end;
type TMasterCtrl = packed record
MyRecord: PMyRecord;
end;
正如 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;
也就是说,您的代码还有另外两个问题:
fields[i].GetValue(@Instance)
Instance
已经包含TMasterCtrl
实例的地址。通过使用@
,您将错误的地址传递给GetValue()
。您需要删除@
:fields[i].GetValue(Instance)
不叫
rType.Free
。TRttiContext
拥有它并将免费为您提供。