退出RTTI相关函数后访问冲突:结果消失

Access violation after going out of a RTTI-related function: Result disappears

以前我有一个函数可以通过 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;

为什么函数结果在函数中定义正确,但在函数外定义不正确?

TRttiProperty 实例属于 TRttiContext 对象。当您的局部变量 ctx 离开范围时,该 TRttiContext 对象将被销毁,并带走它拥有的所有对象,包括您的 TRttiProperty 实例。

您需要确保拥有您使用的任何 RTTI 对象的 TRttiContext 对象至少与对这些拥有的对象的任何引用一样长。实现这一目标的最简单方法可能是使 TRttiContext 对象成为全局变量。