Правильная очистка памяти при работе с JSON

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Re: Правильная очистка памяти при работе с JSON

Сообщение Ichthyander » 14.11.2020 13:00:24

sts писал(а):одно только jData := GetJSON(... намекает (возвращает экземпляр класса который создает внутри) что пользоваться этой либой не стоит.


Никаких правил это не нарушает. Да, лучше было бы в названии функции добавить Create, но все равно это ИМХО. Можно и так. Такое разрешается, если экземпляр класса возвращается как результат функции. Но вот если экземпляр класса создается внутри функции или процедуры, переданной через параметр (а такое я встречал, к сожалению), вот это крайне некрасиво получается.
Либа fcl-json вполне себе работоспособная и прозрачная

Добавлено спустя 2 минуты 28 секунд:
P.S. по очистке памяти JSON @iskander все верно ответил топикстартеру, добавить нечего

Добавлено спустя 10 минут 13 секунд:
Разве что могу дать совет, который гипотетически может пригодиться. Бывают случаи, когда после включения экземпляра класса TJSONData в другой JSON объект или массив, может возникнуть задача, что с "включенным" объектом придется работать отдельно и мы не можем гарантировать, что работа не продолжится после очистки корневого объекта. Так как после очистки корневого объекта очищаются все "встроенные" в него экземпляры, то в таком случае можно посоветовать использовать функцию Clone (которая, о, ужас, также возвращает в качестве результата функции сгенерированный объект). Пример:
// add a new sub-array
jArray := TJSONArray.Create;
jArray.Add('North');
jArray.Add('South');
jArray.Add('East');
jArray.Add('West');
jObject.Add('Directions', jArray.Clone);

Обращаем внимание на последнюю строчку в коде: функция Clone создает копию объекта jArray (именно полноценную копию, а не ссылку!), в результате после уничтожения jObject.Free очистится копия jArray. С самим же jArray можно будет работать отдельно и потом обязательно также уничтожить jArray.Free
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 558
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Правильная очистка памяти при работе с JSON

Сообщение java73 » 20.11.2020 11:03:18

Столкнулся примерно с этим же. Проверял в разных вариантах на heaptrc.
Код: Выделить всё
destructor TMorphFabric.Destroy;
var
  Item: TJSONObject;
  Json, jarr: TJSONArray;
  cached: specialize TPair<string,TCachedValue>;
  jsonfile: TStringList;
  str: string;
begin
  if CacheAllowed then begin
    Json := TJSONArray.Create;
    for cached in Cache do
      begin
        jarr := TJSONArray.Create;
        for str in cached.Value.cases do
          jarr.Add(str);
        jarr.Add(GetEnumName(TypeInfo(TGender),Ord(cached.Value.gender)));
        jarr.Add(FormatDateTime('DD.MM.YYYY',cached.Value.lastUse));
        Item := CreateJSONObject([cached.Key, jarr]);
        Json.Add(Item);
      end;
    jsonfile := TStringList.Create;
    jsonfile.Text := Json.FormatJSON();
    jsonfile.SaveToFile(INITIALS_CACHE);
    FreeAndNil(jsonfile);
    FreeAndNil(Json);
    FreeAndNil(Cache);
  end;
  inherited Destroy;
end;

При простой работе (чтение записи из файлового кеша) heaptrc выходит с 0, т.е. все объекты память освободили, при этом явно я уничтожаю только изначальный массив Json, элементы item и jarr я не прямо не трогаю.
Также я написал дженерик функцию для чтения произвольного json-объекта по rest api с использованием synapse, и вот при её вызове heaptrc кроет меня очень долго матом. Я предполагаю, что есть проблема с отслеживанием внутри этого модуля объектов, которые создаются в одном месте, а уничтожаются в другом. Но это только предположение, поскольку все, что я сам создаю, я точно освобождаю. Значит, что-то внутри используемых функций есть еще.
java73
постоялец
 
Сообщения: 253
Зарегистрирован: 21.11.2013 09:08:10

Re: Правильная очистка памяти при работе с JSON

Сообщение iskander » 20.11.2020 12:00:01

Емнип, если у хиптрейса есть отладочная информация, по его выхлопу можно понять, что и где утекло.
iskander
постоялец
 
Сообщения: 382
Зарегистрирован: 08.01.2012 18:43:34

Re: Правильная очистка памяти при работе с JSON

Сообщение java73 » 20.11.2020 14:49:20

О, кстати, свои проблемы с остающимся мусором я решил. Одна половина - моя невнимательность, вторая половина - моя любовь к сокращению кода и функциональному стилю, т.е. та же невнимательность, но в заумной обёртке:
1. Метод Free стринглиста внутри условия, которое не всегда отрабатывало, а не после условия
2. Код ниже
Код: Выделить всё
JSONStreamer.JSONToObject(GetJSON(HTTPSender.Document) as TJSONObject, Result);

преобразован в такой:
Код: Выделить всё
  JSON := GetJSON(HTTPSender.Document) as TJSONObject;
  JSONStreamer.JSONToObject(JSON, Result);
  FreeAndNil(JSON);

Вместо красивой одной строчки к сожалению три, но в паскале это основополагающий принцип, вероятно, с которым приходится мириться после каких-нибудь питонов.
java73
постоялец
 
Сообщения: 253
Зарегистрирован: 21.11.2013 09:08:10

Re: Правильная очистка памяти при работе с JSON

Сообщение Ichthyander » 20.11.2020 18:32:40

java73 писал(а):О, кстати, свои проблемы с остающимся мусором я решил. Одна половина - моя невнимательность, вторая половина - моя любовь к сокращению кода и функциональному стилю, т.е. та же невнимательность, но в заумной обёртке:
1. Метод Free стринглиста внутри условия, которое не всегда отрабатывало, а не после условия
2. Код ниже
Код: Выделить всё
JSONStreamer.JSONToObject(GetJSON(HTTPSender.Document) as TJSONObject, Result);

преобразован в такой:
Код: Выделить всё
  JSON := GetJSON(HTTPSender.Document) as TJSONObject;
  JSONStreamer.JSONToObject(JSON, Result);
  FreeAndNil(JSON);

Вместо красивой одной строчки к сожалению три, но в паскале это основополагающий принцип, вероятно, с которым приходится мириться после каких-нибудь питонов.

А так?
Код: Выделить всё
JSONStreamer.JSONToObject(HTTPSender.Document, Result);
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 558
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Пред.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru