使用
1 | ReportMemoryLeaksOnShutdown := True; |
来开启自带的内存泄露检测
引用 System.JSON单元
测试代码如下:
procedure TForm1.FormCreate(Sender: TObject);
var
jo:TJsonObject;
joo:TJsonObject;
ja:TJsonArray;
jao:TJsonValue;
begin
//状况1 单个JSON对象 直接释放即可
jo := TJSONObject.ParseJSONValue('{"A":true}') as TJSONObject;
//jo.Free;
FreeAndNil(jo);
//状况2 数组对象 在遍历时, 无需对遍历的对象进行释放
ja := TJSONObject.ParseJSONValue('[{"A":true},{"B":false}]') as TJSONArray;
for jao in ja do
begin
OutputDebugString(PChar(jao.ToString));
// jao.Free; 这样会报异常 因为其实这里的jao仅仅是一个指针,而不是拷贝出来的对象
end;
//ja.Free;
FreeAndNil(ja);
//状况3 Values['Name'] 出来的对象, 其实这里和状况2类似
jo := TJSONObject.ParseJSONValue('{"A": {"B":true}}') as TJSONObject;
joo := jo.Values['A'] as TJSONObject;
OutputDebugString(PChar(joo.ToString));
//joo.Free;
//FreeAndNil(joo); //这样也会出错
FreeAndNil(jo);
end; |
为什么会这样, 看源码:
destructor TJSONObject.Destroy; var Member: TJSONAncestor; I: Integer; begin if FMembers <> nil then begin for i := 0 to FMembers.Count - 1 do begin Member := TJSONAncestor(FMembers[I]); if Member.GetOwned then Member.Free; end; FreeAndNil(FMembers); end; inherited Destroy; end; destructor TJSONArray.Destroy; var Element: TJSONAncestor; I: Integer; begin if FElements <> nil then begin for I := 0 to FElements.Count - 1 do begin Element := TJSONAncestor(FElements[I]); if Element.GetOwned then Element.Free; end; FreeAndNil(FElements); end; inherited Destroy; end; |
也就是说,这棵对象的树会自己处理树枝的生命周期, 因此只要管好 ParseJSONValue 出来的那个对象即可