Перейти к содержанию
Fire Monkey от А до Я
  • 0

[Spring4D] Освобождение памяти объектов интерфейсного типа


Aptem

Вопрос

Коллеги, не могу разобраться с освобождением памяти объектов интерфейсного типа.

 

Вот есть у меня переменная:

var surveyList : IList<TSurvey>;

То есть это список простеньких объектов. Предположим, TSurvey - класс, содержащий два поля: Id и Name.

 

Есть функция которая заполняет этот список, например, из базы данных:

function GetList () : IList<TSurvey>
var
  list : IList<TSurvey>;
  i : Integer;
  item : TSurvey;
begin
  list := TCollections.CreateList<TSurvey>;

   for i := 0 to 10 do 
   begin
     item := TSurvey.Create ();
     item.Id := берем_например_из_БД
     item.Name := берем_например_из_БД
     list.Add ( item );
   end;
   Result := list;
end;

И дальше необходимо в течении жизни программы обновлять этот список, то есть вызывать эту функцию.

surveyList := GetList ();

Так вот, при каждом вызове функции выделяется определенная память, например, 5 Мб. И каждый раз при вызове этой функции общий объем оперативной памяти увеличивается на 5 Мб (это видно из Диспетчера задач). Но ведь память интерфейсного объекта освобождается при величине счетчика ссылок равной 0. Почему тогда идет увеличение?

 

Пытался и так сделать:

if Assigned ( surveyList ) then begin
  surveyList.Clear ();
  surveyList := nil;
end;

surveyList := GetList ();

Но это не помогает. Как правильно освободить память?

Изменено пользователем Brovin Yaroslav
Отформатирован код
Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Спасибо за ответ. Но у интерфейса такого метода нет. Если приводить каждый элемент списка к определенному типу, то теряется все изящество использования интерфейсов как абстракции.

Ссылка на комментарий
  • 0

Добрый день,

 

Покажите, пожалуйста, как объявлен тип TCollections.

 

Здравствуйте.

 

Это класс фреймворка Spring4D. Кстати, всем рекомендую. Работа со списками очень удобна, есть LINQ-подобные конструкции для поиска элементов с различными предикатами, а также неплохо реализован IoC-контейнер.

  TCollections = class
  public
    class function CreateList<T>: IList<T>; overload; static;
    class function CreateList<T>(const comparer: IComparer<T>): IList<T>; overload; static;
    class function CreateList<T>(const comparer: TComparison<T>): IList<T>; overload; static;
    class function CreateList<T>(const values: array of T): IList<T>; overload; static;
    class function CreateList<T>(const values: IEnumerable<T>): IList<T>; overload; static;
    class function CreateList<T: class>(ownsObjects: Boolean): IList<T>; overload; static;
    class function CreateList<T: class>(const comparer: IComparer<T>; ownsObjects: Boolean): IList<T>; overload; static;
    class function CreateList<T: class>(const comparer: TComparison<T>; ownsObjects: Boolean): IList<T>; overload; static;
    class function CreateObjectList<T: class>(ownsObjects: Boolean = True): IList<T>; overload; static;
    class function CreateObjectList<T: class>(const comparer: IComparer<T>; ownsObjects: Boolean = True): IList<T>; overload; static;
    class function CreateObjectList<T: class>(const comparer: TComparison<T>; ownsObjects: Boolean = True): IList<T>; overload; static;
    class function CreateObjectList<T: class>(const values: array of T; ownsObjects: Boolean = True): IList<T>; overload; static;
    class function CreateObjectList<T: class>(const values: IEnumerable<T>; ownsObjects: Boolean = True): IList<T>; overload; static;
    class function CreateInterfaceList<T: IInterface>: IList<T>; overload; static;
    class function CreateInterfaceList<T: IInterface>(const comparer: IComparer<T>): IList<T>; overload; static;
    class function CreateInterfaceList<T: IInterface>(const comparer: TComparison<T>): IList<T>; overload; static;
    class function CreateInterfaceList<T: IInterface>(const values: array of T): IList<T>; overload; static;
    class function CreateInterfaceList<T: IInterface>(const values: IEnumerable<T>): IList<T>; overload; static;

    class function CreateDictionary<TKey, TValue>: IDictionary<TKey, TValue>; overload; static;
    class function CreateDictionary<TKey, TValue>(capacity: Integer): IDictionary<TKey, TValue>; overload; static;
    class function CreateDictionary<TKey, TValue>(const comparer: IEqualityComparer<TKey>): IDictionary<TKey, TValue>; overload; static;
    class function CreateDictionary<TKey, TValue>(capacity: Integer; const comparer: IEqualityComparer<TKey>): IDictionary<TKey, TValue>; overload; static;
    class function CreateDictionary<TKey, TValue>(ownerships: TDictionaryOwnerships): IDictionary<TKey, TValue>; overload; static;
    class function CreateDictionary<TKey, TValue>(ownerships: TDictionaryOwnerships; capacity: Integer): IDictionary<TKey, TValue>; overload; static;
    class function CreateDictionary<TKey, TValue>(ownerships: TDictionaryOwnerships; capacity: Integer; const comparer: IEqualityComparer<TKey>): IDictionary<TKey, TValue>; overload; static;
    class function CreateDictionary<TKey, TValue>(dictionary: Generics.Collections.TDictionary<TKey, TValue>; ownership: TOwnershipType): IDictionary<TKey, TValue>; overload; static;

    class function CreateMultiMap<TKey, TValue>: IMultiMap<TKey, TValue>; overload; static;
    class function CreateMultiMap<TKey, TValue>(ownerships: TDictionaryOwnerships): IMultiMap<TKey, TValue>; overload; static;

    class function CreateStack<T>: IStack<T>; overload; static;
    class function CreateStack<T: class>(ownsObjects: Boolean): IStack<T>; overload; static;
    class function CreateStack<T>(const values: array of T): IStack<T>; overload; static;
    class function CreateStack<T>(const values: IEnumerable<T>): IStack<T>; overload; static;

    class function CreateQueue<T>: IQueue<T>; overload; static;
    class function CreateQueue<T: class>(ownsObjects: Boolean): IQueue<T>; overload; static;
    class function CreateQueue<T>(const values: array of T): IQueue<T>; overload; static;
    class function CreateQueue<T>(const values: IEnumerable<T>): IQueue<T>; overload; static;

    class function CreateSet<T>: ISet<T>; overload; static;
    class function CreateSet<T>(const comparer: IEqualityComparer<T>): ISet<T>; overload; static;
    class function CreateSet<T>(const values: array of T): ISet<T>; overload; static;
    class function CreateSet<T>(const values: IEnumerable<T>): ISet<T>; overload; static;

    ///	<summary>
    ///	  Returns an empty <see cref="IEnumerable<T>" /> that has the
    ///	  specified type argument.
    ///	</summary>
    ///	<typeparam name="T">
    ///	  The type to assign to the type parameter of the returned generic
    ///	  <see cref="IEnumerable<T>" />.
    ///	</typeparam>
    ///	<returns>
    ///	  An empty <see cref="IEnumerable<T>" /> whose type argument is
    ///	  <i>T</i>.
    ///	</returns>
    class function Empty<T>: IEnumerable<T>; static;

    class function Query<T>(const source: TArray<T>): IEnumerable<T>; overload; static;
    class function Query<T>(const source: TEnumerable<T>): IEnumerable<T>; overload; static;

    class function Range(start, count: Integer): IEnumerable<Integer>; static;

    class function Repeated<T>(const element: T; count: Integer): IEnumerable<T>; static;

    class function Select<T, TResult>(const source: IEnumerable<T>;
      const selector: TFunc<T, TResult>): IEnumerable<TResult>; overload; static;
  end;

Ссылка на комментарий
  • 0

поддерживаю. стандартные коллекции и рядом не стояли. особенно если вы хотите писать реально ООПшный код, используя многоуровневое наследование коллекций. 

со стандартными генериками ide не справляется

Ссылка на комментарий
  • 1
  • Администраторы

Ваша ошибка в том, что вы используете не тот список. Вы используете TList, который не удаляет свои элементы в момент разрушения списка. Поэтому ваша утечка - это не распущенные экземпляры TSurvey. Вместо этого нужно использовать TObjectList, который при установке ownsObjects = True, удаляем свои элементы.

 

Итого, код создания списка должен быть таким:

function GetList: IList<TSurvey>;
var
  list : IList<TSurvey>;
  i : Integer;
  item : TSurvey;
begin
  list := TCollections.CreateObjectList<TSurvey>(True); // <-- !!!

  for i := 0 to 10 do
  begin
    item := TSurvey.Create ();
    item.Id := Random(100);
    item.Name := I.ToString;
    list.Add ( item );
  end;
  Result := list;
end;

Можно поиграться с проектом в Windows MemoryLeak.zip

Ссылка на комментарий
Гость
Эта тема закрыта для публикации ответов.
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...