内存泄漏和 JSON 数据

Memory leaks and JSON data

我有一个应用程序,它从磁盘读取 JSON 数据字符串以创建一个字符串网格列表股票(代码、持有数量、成本),然后调用股票经纪人 API 来填写当前价格和价值。它可以工作,但下面的代码会导致内存泄漏,但是虽然有很多关于如何访问 JSON 数组 none 中的数据的互联网帖子,但我可以找到讨论如何释放分配的内存。有人可以帮忙吗?如果重要的话,我使用 Delphi Berlin 10.1 和 Indy 10.6。有 3 页数据,一些股票在 2 页上,sTickers 是一个字符串列表,其中填充了每个股票代码(大约 10 个),并且 3 个字符串网格(tabGrids[0..2] 上大约有 14 个股票持有量在页面控件上。

问题代码为:

      JSONArray := TJSONObject.ParseJSONValue(s) as TJSONArray;
      if JSONarray = nil then
      begin
        ShowMessage('An error occurred reading the data file, section = [' +
                    iniSection[tabpage] + '].');
        continue;
      end;
      for row := 0 to JSONArray.Count - 1 do
      begin
        s := (JSONArray.Items[row] as TJSONObject).Get('ticker').JSONValue.Value;
        SL.Add(s);
      end;
      CombineStrings(sTickers, SL);
      tabGrids[tabpage].RowCount := SL.Count + 2; //set row count
      for row := 1 to SL.Count do
      begin //add fixed data to each grid row
        tabGrids[tabpage].Cells[0, row] := SL[row - 1];
        tabGrids[tabpage].Cells[4, row] := (JSONArray.Items[row - 1] as TJSONObject).Get('qty').JSONValue.Value;
        tabGrids[tabpage].Cells[6, row] := (JSONArray.Items[row - 1] as TJSONObject).Get('cost').JSONValue.Value;
        tabGrids[tabpage].Cells[1, row] := (JSONArray.Items[row - 1] as TJSONObject).Get('name').JSONValue.Value;
        if not tryStrToFloat(tabGrids[tabpage].Cells[4, row], qty) then qty := 0;
        if not tryStrToFloat(tabGrids[tabpage].Cells[6, row], price) then price := 0;
        tabGrids[tabpage].Cells[6, row] := FloatToStr(qty*price/100);
      end;
      tabGrids[tabpage].Width := tabGrids[tabpage].ColWidths[0] +
        tabGrids[tabpage].ColWidths[1] + tabGrids[tabpage].ColWidths[2] +
        tabGrids[tabpage].ColWidths[3] + tabGrids[tabpage].ColWidths[4] +
        tabGrids[tabpage].ColWidths[5] + tabGrids[tabpage].ColWidths[6] + 18;
      SL.Clear;
    end;
    JSONArray.Free;

我假设 (JSONArray.Items[row] as TJSONObject).Get('ticker').JSONValue.Value 行正在分配我不会释放的内存但我不知道如何释放它。或者,也许有更好的方法来获取数据。

您提到了 3 页数据。您正在泄漏 2 x TJasonArray,并且在没有相应开始的 end; 之后的最后一行释放了一个 TJasonArray

据此我得出结论,您有一个循环(您没有显示)您 运行 三次。每次创建 TJasonArray 但只释放一个时,在循环 end; 之后,将 JSonArray.Free; 移动到 end;.

之前

为了更简单,您可以只使用 TJSONValue 来解析并在最后释放它,而无需释放数组:[​​=16=]

var
  Value: TJsonValue
  // ...
begin
  Value := TJSONObject.ParseJSONValue(s);
  try
    Ar := Value.FindValue('item') as TJSONArray;
  finally
    FreeAndNil(Value);
  end;
end;

而不是:

tabGrids[tabpage].Cells[1, row] := (JSONArray.Items[row - 1] as TJSONObject).Get('name').JSONValue.Value;

你可以做到

tabGrids[tabpage].Cells[1, row] := JSONArray.Items[row - 1].GetValue<string>('name');

然后,在释放数组之前有一个 end;,如果它是上层循环,您将有内存泄漏。使用 try finally 块来释放它和 TStringList.