使用
1
|
ReportMemoryLeaksOnShutdown := True;
|
来开启自带的内存泄露检测
引用 System.JSON
单元
测试代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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;
|
为什么会这样, 看源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
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
出来的那个对象即可