Delphi TJSONArray内存泄漏:无法释放JSON容器/对象
下图列出了以下代码导致的内存泄漏: 方法:Delphi TJSONArray内存泄漏:无法释放JSON容器/对象,delphi,memory-leaks,delphi-xe6,Delphi,Memory Leaks,Delphi Xe6,下图列出了以下代码导致的内存泄漏: 方法: procedure TInformationSource.SetConfig; var vJSONConfigList : TStringList; vCurrentFileName : string; vDebugString : string; begin if iCJSONByteStream = nil then iCJSONByteStream := TBytesStream.Create;
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;
//...
现在,析构函数中最后5条FreeandNil语句都传递了访问冲突。对于TJSONArray实例,我目前的理解是,要么您无法释放和取消TJSONArray对象,因为您无法使用来构造它们。首先,创建编译器会抱怨您已使用虚拟方法从类实例化了对象,要么您只能使用TJSONValue.GetValue。然而,我不确定这是否是真的,如果是真的,我也不确定为什么会有这种差异。见下一段
TJONValue是密封类TJSONArray和TJSONObject的虚拟基类,因此是不可扩展类。我正在通过调用TJSONObject.ParseJSONValue和TJSONValue.GetValue创建后一个对象的实例,其中X是要返回的值TJSONArray、TJSONObject的类型
现在,我似乎在调用TObjectTJSONObject.ParseJSONValue…,TByteArray(返回有效值)创建的TJSONObject实例上获得FreeandNil的访问冲突,而在调用TJSONValue.GetValuekeystring创建的TJSONObject上没有获得访问冲突
我不明白这是为什么
TMoveArray泄漏是否与泄漏的TJSONArray对象有关联
另外一个问题是-如何释放与TBytes实例关联的内存,TBytes实例是泛型TArray的实例,其中类型约束是type Bytes?图像中的一些内存泄漏也与这些相关。或者这是自动完成的,因此不会导致下面的内存泄漏列表。这是一个充满泄漏的代码。SetConfig有一个未被释放的本地TStringList,它甚至没有被使用。循环正在为多个文件调用TJSONObject.ParseJSONValue,但将结果分配给单个重用变量,而每次都不释放前一个对象。我怀疑您打算将iCJSONConfigData添加到iCJSONData,但忘记了这样做。如果是这种情况,则析构函数不应释放iCJSONConfigData,因为iCJSONData拥有它,只需释放iCJSONData本身,它将为您释放包含的对象。我已在FastMM上激活泄漏检测,并且在其当前状态下未报告泄漏。不要释放iCJSONConfigData,因为iCJSONData拥有它,仅仅释放iCJSONData本身,这确实是问题的一部分。事实上,我已经将iCJSONConfigData对象的成员分配给了第二个五个对象,因为它们与业务对象的属性相关联,这些业务对象只是在iCJSONConfig数据中公开了叶节点JSON对象,iCJSONConfig数据由一个大的JSON配置文件填充。因此,当我销毁第二组时,我正在释放已经释放的部分iCJSONConfig数据。感谢heaps Remy。在XE6和XE7中向析构函数添加异常处理程序的状态如何?因为异常处理程序阻止继承,这仍然是一个坏主意吗?无论如何都不应该允许析构函数引发异常。如果您正确地编写对象代码,析构函数应该始终能够清理处于已知状态的资源。在析构函数中没有什么是未知的。