Delphi TJSONArray内存泄漏:不能FreeandNil JSON容器/对象

时间:2015-01-29 07:24:52

标签: delphi memory-leaks delphi-xe6

下图显示了以下代码引入的内存泄漏:

方法:

    procedure TInformationSource.SetConfig;
var
  vJSONConfigList : TStringList;
  vCurrentFileName : string;
  vDebugString : string;

begin

    if iCJSONByteStream = nil then
      iCJSONByteStream := TBytesStream.Create;

    if vJSONConfigList = nil then
      vJSONConfigList := TStringList.Create;

    for vCurrentFileName in uCInformationSourceConfigFileNames do
    begin

      iCJSONBytes := TFile.ReadAllBytes(vCurrentFileName);
      iCJSONAsStr := TFile.ReadAllText(vCurrentFileName);

      fMain.jdInformationSource.JsonText := iCJSONAsStr;
      fMain.jtvInformationSource.LoadJson(false);

      if iCConfigsList = nil then
        iCConfigsList := TStringList.Create;
      if iCJSONData = nil then
        iCJSONData := TJSONArray.Create; // TJSONObject.Create();


      iCJSONConfigData := TJSONObject.ParseJSONValue(iCJSONBytes , 0) as TJSONObject;

      vDebugString := iCJSONConfigData.ToString;
      iCEndpoint             := GetActiveEndpoint;
      iCHeaderParams         := GetActiveHeaderParams;
      iCActiveAuthParams     := GetActiveAuthParams;
      iCActiveProtocolParams := GetActiveProtocolParams;
      iCActiveSourceName     := GetActiveSourceName;
end;end;

对象的解构者:

    destructor TInformationSource.Destroy;
begin

  FreeandNil(iCHeaderParams);         // Okay
  FreeandNil(iCActiveProtocolParams); // Okay
  FreeandNil(iCJSONByteStream);       // Okay
  FreeandNil(iCConfigsList);          // Okay
  FreeandNil(uCInformationSourceConfigFileNames);  //Okay

  //FreeandNil(iCJSONConfigData);      // nil pointer access violation - Why?
  //FreeandNil(iCActiveAuthParams);    // nil pointer access violation - Why?
  //FreeandNil(iCJSONData);            // nil pointer access violation because TJSONArray Virtual base class?
  //FreeandNil(iCAuthPairs);           // nil pointer access violation because TJSONArray Virtual base class?

  inherited;
end;

声明:

//...
       private
   iCJSONData             : TJSONArray;
    iCAuthPairs            : TJSONArray;
    iCHeaderParams         : TJSONObject;
    iCActiveAuthParams     : TJSONArray;
    iCActiveProtocolParams : TJSONObject;
    iCActiveSourceName     : String;
    iCJSONAsStr : string;
    iCJSONBytes : TBytes;
    iCJSONByteStream : TBytesStream;
    iCConfigsList : TStringList;
    iCJSONConfigData : TJSONObject;
//...

Memory leaks caused by the above code

现在,析构函数中的最后5个FreeandNil语句都会传递访问冲突。对于TJSONArray实例,我此时的理解是要么你不能FreeandNil TJSONArray对象因为你不能用.Create构造它们(编译器抱怨你已经用虚方法从类中实例化了一个对象) - 或者你如果使用TJSONValue.GetValue实例化它们,则只能FreeandNil。但是我不确定这是否属实,如果是,我不确定为什么会有这种差异。见下一段。

TJONValue是一个密封且因此无法扩展的类TJSONArray和TJSONObject的虚拟基类。我通过调用TJSONObject.ParseJSONValue和TJSONValue.GetValue来创建后一个对象的实例,其中X是要返回的值的类型(TJSONArray,TJSONObject)。

现在看起来我在通过调用TObject(TJSONObject.ParseJSONValue(...,TByteArray))创建的TJSONObject实例上获取FreeandNil的访问冲突(返回有效值),而我没有获得访问冲突通过调用TJSONValue.GetValue(keystring)创建的TJSONObjects;

我不明白为什么会这样。

TMoveArray泄漏是否与泄漏的TJSONArray对象相关联?

另外一个问题是 - 如何释放与TBytes实例关联的内存,这些内存是类型约束为字节类型的泛型TArray的实例?图像中的一些内存泄漏也与那些内存泄漏相关联。或者这是自动完成的,因此不会对下面的内存泄漏列表做出贡献。

0 个答案:

没有答案