【问题标题】:Error while trying to access class attributes尝试访问类属性时出错
【发布时间】:2012-03-18 22:33:16
【问题描述】:

我有这门课:

{$RTTI EXPLICIT FIELDS([vcProtected]) PROPERTIES([vcProtected])}
const
  PP_VEHICLE_FIELD = 'VEICULO_ID';
  PP_DRIVER_FIELD = 'MOTORISTA_ID';
  PP_TRIP_FIELD = 'VIAGEM_ID';
  PP_DATE = 'DATA';

type
  [TAttrDBTable('NONE')]
  TReportItem = class(TObject)
  protected
    [TAttrDBField(PP_VEHICLE_FIELD)]
    FVeiculoId: integer;
    [TAttrDBField(PP_DRIVER_FIELD)]
    FMotoristaId: integer;
    [TAttrDBField(PP_TRIP_FIELD)]
    FViagemId: integer;
    [TAttrDBField(PP_DATE)]
    FDataRelatorio: TDate;
  published
    class function GetTableName<T: class, constructor>: string;
  end.

class function TReportItem.GetTableName<T>: string;
var
  LRttiContext: TRttiContext;
  LRttiType: TRttiType;
  LCustomAttribute: TCustomAttribute;
  LType: T;
begin
  LType := T.Create;
  try
    LRttiContext := TRttiContext.Create;
    LRttiType := LRttiContext.GetType(LType.ClassType);
    for LCustomAttribute in LRttiType.GetAttributes do
      if LCustomAttribute is TAttrDBTable then
      begin
        Result := TAttrDBTable(LCustomAttribute).TableName;
        Break;
      end;
  finally
    LType.Free;
  end;
end;

我这样称呼它:TReportItem.GetTableName&lt;TReportItem&gt;; &lt;&gt; 可以是任何继承 TReportItem 的类。

但是,有时当我在命令LRttiType.GetAttributes 中调用:TReportItem.GetTableName 时,我会遇到访问冲突,有时不会,这取决于“编译”。它像魔术一样工作并停止工作。 我不知道发生了什么。有人可以给我一个提示吗?

问题出在GetAttributes 上,如果我用它来获取字段、方法等中的属性。它会给我访问冲突。是否有一些指令我必须打开或关闭才能使用它?

如果我使用 Shift+F9 编译,GetAttributes 给我 AV,如果我修改单元中的任何行并使用 F9 GetAttributes 进行编译。

不仅在我的机器上,其他 8 位程序员也有同样的问题。德尔福 XE。

rtti.pas中这段代码出现错误:

function FindCtor(AttrType: TRttiInstanceType; CtorAddr: Pointer): TRttiMethod;
type
  PPPointer = ^PPointer;
var
  p: PByte;
  imp: Pointer;
begin
  for Result in AttrType.GetMethods do
    if Result.CodeAddress = CtorAddr then
      Exit;
  // expect a package (i.e. DLL) import
  p := CtorAddr;
  Assert(p^ = $FF); // $FF $25 => indirect jump m32
  Inc(p);
  Assert(p^ = $25);
  Inc(p);
  imp := PPPointer(p)^^; //ERROR HAPPENS HERE
  for Result in attrType.GetMethods do
    if Result.CodeAddress = imp then
      Exit;
  Result := nil;
end;

【问题讨论】:

  • 你能把你的电话显示给TReportItem.GetTableName吗?
  • 拿到AV后,LRttiType有什么价值?
  • @SaCi 你写的,你在尝试获取字段和属性的属性时得到 AV,但在上面的代码中 getAttributes 仅用于获取类属性。 (如果您的字段和道具是公开的,那么在我看来,您也必须在 $RTTI 指令中包含 vcPublic)
  • 顺便说一下,你的函数不需要泛型。如果T 应该是从TReportItem 继承的类,那么只需调用T.GetTableName。在函数中,将T 替换为Self。您也可以将LType.ClassType 替换为Self。将LType 声明为TReportItem
  • @SaCi,感谢您的提议,这似乎确实是一个 RTTI 错误,请查看此帖子 stackoverflow.com/questions/7201817/… 和相关的 QC qc.embarcadero.com/wc/qcmain.aspx?d=98261,如果您同意,可以添加一些投票更多地关注质量控制。

标签: delphi attributes rtti


【解决方案1】:

我今天几个小时都遇到了完全相同的问题,Rtti.pas 中 imp := PPPointer(p)^^ 上的相同 AV。

我发现我在我的项目中为 2 个不相关单元中的 2 个属性使用了相同的名称:在我重命名其中一个之后,不再有 AV!

【讨论】:

  • 我有同样的问题并且没有同名的属性我也将.dpr内的单位更改为@SaCi,但错误仍然存​​在
猜你喜欢
  • 1970-01-01
  • 2021-05-21
  • 2013-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-12
  • 2019-08-24
  • 2012-07-06
相关资源
最近更新 更多