退出与RTTI相关的功能后发生访问冲突:结果消失

时间:2018-08-06 11:39:18

标签: delphi rtti

以前,我有一个函数可以通过RTTI获取对象属性并设置其值。现在,我决定将其拆分为TRTTI.GetObjPropTRTTI.SetObjPropValue,以便缓存TRTTI.GetObjProp返回的值并加快数据处理速度。

之后发生奇怪的事情。首先,我突然注意到ctx.GetType可以正常工作,尽管我从未初始化ctx变量。好的,如果我使用TRttiContext.Create()对其进行初始化,那么第二个怪异现象将保持不变:

我调用TRTTI.GetObjProp函数,只要我在此函数中,就定义Result,并且可以使用调试器请求它的属性。当我退出该函数时,我尝试请求rprop变量的相同属性,并获得访问冲突错误。根据调试器的定义,rprop

procedure TConfManager._setValue(indicator: TComponent; name: string; value: OleVariant);
var
  rprop: TRttiProperty;
begin
  rprop := TRTTI.GetObjProp(indicator, name);
  //Access violation here when I try to use rprop
  TRTTI.SetObjPropValue(indicator, rprop, value);
end;

class function TRTTI.GetObjProp(obj: TObject; propName: string): TRttiProperty;
var
  ctx: TRttiContext;
  rtyp: TRttiType;
begin
  if obj = nil then Exit(nil);
  rtyp := ctx.GetType(obj.ClassType);
  Result := rtyp.GetProperty(propName);
end;

为什么我在使用函数时正确定义了函数结果,但是当我退出函数时却没有正确定义?

1 个答案:

答案 0 :(得分:4)

TRttiProperty实例归TRttiContext对象所有。当您的局部变量ctx离开作用域时,该TRttiContext对象将被销毁,并带有它拥有的所有对象,包括您的TRttiProperty实例。

您需要确保拥有使用的任何RTTI对象的TRttiContext对象的生存时间至少与对那些拥有的对象的任何引用一样长。最简单的方法可能是使TRttiContext对象成为全局变量。