Jak prawidłowo zwolnić JSONObject?

0

Witam,

jak prawidłowo powinno wyglądać zwolnienie obiektów w poniższym kodzie? Próbuję na końcu zwalniać jso.Free ale wali Accessami i kod są wycieki pamięci.

unit JSONMobile;

interface

uses JSON, System.Classes, System.Generics.Collections;

type
  TOpeningDays = class
    private
      DayName: string;
      OpenFrom: string;
      OpenTo: string;
      IsOpen: Boolean;
  end;


type
  TMenuItem = class
    private
      FOpeningDayList: TOpeningDays;
      FDayList: TList;
      FJSONContextMenu: string;
      FTabVisible: boolean;
      procedure ParseOpeningDays(AArrayName: string; AJSONObject: TJSONObject);
      procedure ParseOpeningHours(ADayName: string; AJSONObject: TJSONObject);
      procedure ParseTabDiscounts(AJSONObject: TJSONObject);
      procedure ParseTabAbout(AJSONObject: TJSONObject);
      procedure ParseTabGallery(AJSONObject: TJSONObject);
      procedure ParseTabPrices(AJSONObject: TJSONObject);
      procedure ParseTabOpinions(AJSONObject: TJSONObject);
    public
      constructor Create;
      destructor Destroy; override;
      procedure ParseJSONArray(AArrayName, ATabName: string; AJSONObject: TJSONObject);
      property JSONContextMenu: string read FJSONContextMenu write FJSONContextMenu;
      property TabVisible: boolean read FTabVisible write FTabVisible;
  end;

implementation

{ TTabAbout }

constructor TMenuItem.Create;
begin
  FDayList := TList.Create;
end;

destructor TMenuItem.Destroy;
begin
  if Assigned(FOpeningDayList) then
    FOpeningDayList.Free;

  FDayList.Free;
  inherited;
end;

procedure TMenuItem.ParseJSONArray(AArrayName, ATabName: string; AJSONObject: TJSONObject);
var
  jsa: TJSONArray;
  jsv: TJSONValue;
  jsp: TJSONPair;
  jso: TJSONObject;
  i: integer;
begin

  jsv := AJSONObject.GetValue(AArrayName);
  jsp := AJSONObject.Get(AArrayName);

  if jsp <> nil then
  begin
    jsa := jsv as TJSONArray;

    for i := 0 to jsa.Count - 1 do
    begin
      jso := jsa.Items[i] as TJsonObject;

      // Pętla po obiektach zakładek menu
      for jsp in jso do
      begin
        if (jsp.JsonString.Value = 'TAB_DISCOUNTS') and (jsp.JsonString.Value = ATabName)  then
          ParseTabDiscounts(jso)
        else if (jsp.JsonString.Value = 'TAB_ABOUT') and (jsp.JsonString.Value = ATabName) then
          ParseTabAbout(jso)
        else if (jsp.JsonString.Value = 'TAB_GALLERY') and (jsp.JsonString.Value = ATabName) then
          ParseTabGallery(jso)
        else if (jsp.JsonString.Value = 'TAB_PRICES') and (jsp.JsonString.Value = ATabName) then
          ParseTabPrices(jso)
        else if (jsp.JsonString.Value = 'TAB_OPINIONS') and (jsp.JsonString.Value = ATabName) then
          ParseTabOpinions(jso);
      end;

      // Przypisujemy JSONMenu
      if AArrayName = 'TABS' then
      begin
        JSONContextMenu := jso.ToJSON;
        //jso.Free;
      end;
    end;
  end;
end;

procedure TMenuItem.ParseOpeningDays(AArrayName: string;
  AJSONObject: TJSONObject);
var
  jsa: TJSONArray;
  jsv: TJSONValue;
  jsp: TJSONPair;
  jso: TJSONObject;
  i: integer;
begin

  jsv := AJSONObject.GetValue(AArrayName);

  if jsv <> nil then
  begin
    jsa := jsv as TJSONArray;

    for i := 0 to jsa.Count - 1 do
    begin
      jso := jsa.Items[i] as TJsonObject;

      // Pętla po obiektach zakładek menu
      for jsp in jso do
      begin
        if jsp.JsonString.Value = 'MONDAY' then
          ParseOpeningHours('MONDAY', jso)
        else if jsp.JsonString.Value = 'TUESDAY' then
          ParseOpeningHours('TUESDAY', jso)
        else if jsp.JsonString.Value = 'WEDNESDAY' then
          ParseOpeningHours('WEDNESDAY', jso)
        else if jsp.JsonString.Value = 'THURSDAY' then
          ParseOpeningHours('THURSDAY', jso)
        else if jsp.JsonString.Value = 'FRIDAY' then
          ParseOpeningHours('FRIDAY', jso)
        else if jsp.JsonString.Value = 'SATURDAY' then
          ParseOpeningHours('SATURDAY', jso);
      end;

      //jso.Free;
    end;


  end;
end;

procedure TMenuItem.ParseOpeningHours(ADayName: string;
  AJSONObject: TJSONObject);
var
  jsa: TJSONArray;
  jsv: TJSONValue;
  jsp: TJSONPair;
  jso: TJSONObject;
  i: integer;
  OpeningDayList: TOpeningDays;
  LDayName: string;
begin
  jsv := AJSONObject.GetValue(ADayName);

  if ADayName = 'MONDAY' then
    LDayName := 'Poniedziałek'
  else if ADayName = 'TUESDAY' then
    LDayName := 'Wtorek'
  else if ADayName = 'WEDNESDAY' then
    LDayName := 'Środa'
  else if ADayName = 'THURSDAY' then
    LDayName := 'Czwartek'
  else if ADayName = 'FRIDAY' then
    LDayName := 'Piątek'
  else if ADayName = 'SATURDAY' then
    LDayName := 'Sobota';

  jsa := jsv as TJSONArray;

  for i := 0 to jsa.Count - 1 do
  begin
    jso := jsa.Items[i] as TJsonObject;

    // Pętla po obiektach zakładek menu
    OpeningDayList := TOpeningDays.Create;
    OpeningDayList.DayName := LDayName;
    OpeningDayList.IsOpen := jso.GetValue('From') <> nil;

    for jsp in jso do
    begin
      if jsp.JsonString.Value = 'From' then
        OpeningDayList.OpenFrom := jsp.JsonValue.Value
      else if jsp.JsonString.Value = 'To' then
        OpeningDayList.OpenTo := jsp.JsonValue.Value;
    end;

    FDayList.Add(OpeningDayList);
  end;
end;

procedure TMenuItem.ParseTabAbout(AJSONObject: TJSONObject);
var
  jsa: TJSONArray;
  jsv: TJSONValue;
  jsp: TJSONPair;
  jso: TJSONObject;
  i: integer;
begin

  jsv := AJSONObject.GetValue('TAB_ABOUT');

  if jsv <> nil then
  begin
    jsa := jsv as TJSONArray;

    for i := 0 to jsa.Count - 1 do
    begin
      jso := jsa.Items[i] as TJsonObject;

      for jsp in jso do
      begin
        if jsp.JsonString.Value = 'TabVisible' then
        begin
          if jsp.JsonValue.Value = 'True' then
            TabVisible := True
          else
            TabVisible := False;
        end
        else if jsp.JsonString.Value = 'OPENING_HOURS' then
          ParseOpeningDays('OPENING_HOURS', jso);
      end;
    end;
  end;

end;

procedure TMenuItem.ParseTabDiscounts(AJSONObject: TJSONObject);
var
  jsa: TJSONArray;
  jsv: TJSONValue;
  jsp: TJSONPair;
  jso: TJSONObject;
  i: integer;
begin

  jsv := AJSONObject.GetValue('TAB_DISCOUNTS');

  if jsv <> nil then
  begin
    jsa := jsv as TJSONArray;

    for i := 0 to jsa.Count - 1 do
    begin
      jso := jsa.Items[i] as TJsonObject;

      for jsp in jso do
      begin
        if jsp.JsonString.Value = 'TabVisible' then
        begin
          if jsp.JsonValue.Value = 'True' then
            TabVisible := True
          else
            TabVisible := False;
        end
        else if jsp.JsonString.Value = '????' then

      end;
    end;
  end;
end;

procedure TMenuItem.ParseTabGallery(AJSONObject: TJSONObject);
var
  jsa: TJSONArray;
  jsv: TJSONValue;
  jsp: TJSONPair;
  jso: TJSONObject;
  i: integer;
begin

  jsv := AJSONObject.GetValue('TAB_GALLERY');

  if jsv <> nil then
  begin
    jsa := jsv as TJSONArray;

    for i := 0 to jsa.Count - 1 do
    begin
      jso := jsa.Items[i] as TJsonObject;

      for jsp in jso do
      begin
        if jsp.JsonString.Value = 'TabVisible' then
        begin
          if jsp.JsonValue.Value = 'True' then
            TabVisible := True
          else
            TabVisible := False;
        end
        else if jsp.JsonString.Value = '????' then

      end;
    end;
  end;
end;

procedure TMenuItem.ParseTabOpinions(AJSONObject: TJSONObject);
var
  jsa: TJSONArray;
  jsv: TJSONValue;
  jsp: TJSONPair;
  jso: TJSONObject;
  i: integer;
begin

  jsv := AJSONObject.GetValue('TAB_OPINIONS');

  if jsv <> nil then
  begin
    jsa := jsv as TJSONArray;

    for i := 0 to jsa.Count - 1 do
    begin
      jso := jsa.Items[i] as TJsonObject;

      for jsp in jso do
      begin
        if jsp.JsonString.Value = 'TabVisible' then
        begin
          if jsp.JsonValue.Value = 'True' then
            TabVisible := True
          else
            TabVisible := False;
        end
        else if jsp.JsonString.Value = '????' then

      end;
    end;
  end;
end;

procedure TMenuItem.ParseTabPrices(AJSONObject: TJSONObject);
var
  jsa: TJSONArray;
  jsv: TJSONValue;
  jsp: TJSONPair;
  jso: TJSONObject;
  i: integer;
begin

  jsv := AJSONObject.GetValue('TAB_PRICES');

  if jsv <> nil then
  begin
    jsa := jsv as TJSONArray;

    for i := 0 to jsa.Count - 1 do
    begin
      jso := jsa.Items[i] as TJsonObject;

      for jsp in jso do
      begin
        if jsp.JsonString.Value = 'TabVisible' then
        begin
          if jsp.JsonValue.Value = 'True' then
            TabVisible := True
          else
            TabVisible := False;
        end
        else if jsp.JsonString.Value = '????' then

      end;
    end;
  end;
end;

end.
0

nie tworzysz go tam to dlaczego chcesz go tam niszczyć?

0

Racja...
Ale skąd te wycieki?

0

przypisz im nil a zwolnić musisz AJSONObject tam gdzie go tworzysz

0

Niestety, nie pomaga. Zrobiłem FreeAndNil

1

Większość dotyczy TOpeningDays to są obiekty więc je nie na TList, bo ta ci sama ich nie zwolni tylko do uses System.Generics.Collections i

constructor TMenuItem.Create;
begin
  FDayList:= TObjectList<TOpeningDays>.Create(True);
end;

i z takiej listy korzystaj a jak masz stare Delphi to ze zwykłego TObjectList z modułu Contnrs (System.Contnrs) i dalej napisz co zostało w wyciekach to się obczai.

0

Korzystam z Delphi XE 10.1 updt 2

Przy kompilacji mam błąd:

[dcc32 Error] JSONMobile.pas(48): E2010 Incompatible types: 'TList' and 'System.Generics.Collections.TObjectList<JSONMobile.TOpeningDays>'

Udało mi się.

W destroy zwalniałem obiekt klasy, a powinienem przeiterować TList i zwolnić jej obiety.

destructor TMenuItem.Destroy;
var
  i: integer;
begin
  for i := 0 to DayList.Count -1 do
    TOpeningDays(DayList.Items[i]).Free;

  DayList.Free;
  inherited;
end;
0

Jak już upierasz się na piechotę zwalniać to

  while DayList.Count > 0 do
    TOpeningDays(DayList.Items[0]).Free;

1 użytkowników online, w tym zalogowanych: 0, gości: 1