Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.07.12;
Скачать: CL | DM;

Вниз

Освобождение памяти TList   Найти похожие ветки 

 
Виталий_______   (2009-05-21 08:04) [0]

Доброе время суток!
Имеется экземпляр класса TList с разнородным содержимым внутри. Необходимо корректно освободить память.
До некоторого времени спасало:

procedure FreeList(var WhatList:TList);
var i:integer;
begin
for i:=0 to WhatList.Count-1 do begin
  TObject(WhatList.Items[i]).Free;
end;
WhatList.Clear;
end;

Все бы хорошо, но обнаружилась такая вещь: если в качестве объекта будет какой-либо класс с собственным деструктором, например

TLineData=class(TObject)
  public
  n0Lin:array of TMyPoint;
  ...
  destructor destruct;
  destructor free;

То возникает такая проблема: при преобразовании во FreeList элемента списка к TObject и выполнении .Free, выполняется деструктор TObject.Free, а не переписанный TLineData.Free. В итоге память под n0Lin:array of TMyPoint; не освобождается.
Как в данном случае правильно поступить (например, получить тип элемента списка или что-то другое существует чего я не знаю)?


 
Palladin ©   (2009-05-21 08:08) [1]

А предупреждения компилятора значит не читаем ни разу? Садись, два.


 
Palladin ©   (2009-05-21 08:09) [2]

И что это еще за два деструктора? Да еще оба скрывающие два фундаментальных метода TObject? Что за отсебятина? Зачем это надо? Ради какой Высшей Цели?


 
Юрий Зотов ©   (2009-05-21 08:28) [3]

> Виталий_______

Не пускаясь в долгие разъяснения:    

TLineData = class(TObject)
 ...
 destructor Destroy; override;
end;

И все нужные действия выполняйте в этом ШТАТНОМ ОДНОМ деструкторе. Не забыв в его конце вызвать inherited.

PS
А чтобы больше не возникало подобных (и многих других) вопросов очень советую четко усвоить суть наследования, полиморфизма и виртуальных методов.


 
Vitaliy_____   (2009-05-21 08:50) [4]

Положим, заменить destruct на destroy проблем нет. Я так понимаю, все дело в override, которое мы не делаем?

inherited в конце стоит, разумеется, так что ничего мы не скрываем, а дополняем.

Остался вопрос, что вызывать в procedure FreeList(var WhatList:TList);
for i:=0 to WhatList.Count-1 do begin
 TObject(WhatList.Items[i]).Free;
Оставить Free или поставить переписанный .destroy?

Лучше уж долгие разъяснения, но понимание, чем тупо вставить готовый код...


 
Palladin ©   (2009-05-21 08:53) [5]

TObject.Free + F1


 
Vitaliy_____   (2009-05-21 08:58) [6]

Как раз читаю, в принципе уже RTFM помогло. Но лучше прочесть дважды :)


 
Dennis I. Komarov ©   (2009-05-21 09:16) [7]


> Оставить Free или поставить переписанный .destroy?

Исходя из этой строки, читать все заного...


 
Vitaliy_____   (2009-05-21 09:48) [8]

Ну зачем же заноВо, там выше нигде не сказано, что Free проверит есть ли объект и вызовет деструктор (...Free verifies that the object reference is not nil before calling Destroy.). Это тут не обсуждалось, ибо есть в справке.


 
Dennis I. Komarov ©   (2009-05-21 09:59) [9]

Free вызовит деструктор того, чей он есть. В твоем случае TObject, который ничего не знает о существовании некоего TMyPoint


 
Ega23 ©   (2009-05-21 10:21) [10]


> Free проверит есть ли объект и вызовет деструктор


Правильно. А вот что такое полиморфизм - ты, похоже, не знаешь.


 
Vitaliy_____   (2009-05-21 11:16) [11]

Странно, может кто-нибудь из знатоков полиморфизма объяснит, чем при уже измененном деструкторе (тут вопрос был в знании объекта TObject а не в понимании наследования), так вот, чем по вашему будет отличаться вызов .destroy и .free у TObject(WhatList.Items[i]), при условии что виртуальный .destroy заменен на соответствующий метод TMyPoint?
В данном случае, разве destroy вызванный самостоятельно и методом free будет отличаться?
И как же
> TObject, который ничего не знает о существовании некоего
> TMyPoint

Для чего тогда мы писали override;, разве не для того, чтобы как раз знал?


 
Юрий Зотов ©   (2009-05-21 11:17) [12]

> Vitaliy_____   (21.05.09 08:50) [4]

> Я так понимаю, все дело в override, которое мы не делаем?

И в этом тоже, но не только. Вы вызываете TObject.Free, а оттуда вызывается ШТАТНЫЙ деструктор, который Вы не перекрыли и поэтому он ничего не освобождает. О Ваших же НОВЫХ деструкторах TObject ничего не знает и поэтому вызвать их не может.

Выводы:
- новые деструкторы выкинуть.
- освобождать память в штатном деструкторе.
- и обязательно объявить его с override.

Тогда Free по-прежнему вызовет штатный деструктор, но это будет уже Ваш деструктор. Он все и освободит.


 
Palladin ©   (2009-05-21 11:22) [13]


> при условии что виртуальный .destroy заменен на соответствующий
> метод TMyPoint?

По подробней в этом месте.


 
Юрий Зотов ©   (2009-05-21 11:22) [14]

> Vitaliy_____  

Вдогонку: если WhatList содержит ТОЛЬКО объекты (пусть даже разных классов), то обычно удобнее использовать TObjectList, а не TList. Детали см. в справке.


 
Vitaliy_____   (2009-05-21 11:42) [15]


> Юрий Зотов ©   (21.05.09 11:17) [12]

Слава богу, хоть кто-то написал подробно, а то я уж сомневался, правильно ли я понимаю.
> Palladin ©
Подробнее в [12] - я понимаю точно также.

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


 
Dennis I. Komarov ©   (2009-05-21 11:51) [16]


> Для чего тогда мы писали override;, разве не для того, чтобы
> как раз знал?


Зайди в "генофонд дельфы" и посмотри как происходит наследование классов и описываются деструкторы. Будет проще понять...


 
Ega23 ©   (2009-05-21 11:54) [17]


> весь вопрос был в замене нужного virtual деструктора.


Не надо деструкторы заменять. Не будет ничего хорошего. А плохо - будет.


 
Dennis I. Komarov ©   (2009-05-21 12:58) [18]


> Имеется экземпляр класса TList с разнородным содержимым
> внутри.

да, на сколько разнородно это содержимое? Может будет достаточно if ... is ... then?


 
icWasya ©   (2009-05-21 15:05) [19]

>Ega23 ©   (21.05.09 11:54) [17]
>Не надо деструкторы заменять ...

Деструкторы надо не заменять, а перекрывать -

TLineData = class(TObject)
...
destructor destroy; override;

end;
...

destructor TLineData.destroy;
begin
 ....
 inherited;
end;


А  метод Free - вообще не трогать. Это не деструктор.


 
Ega23 ©   (2009-05-21 15:51) [20]


> Деструкторы надо не заменять, а перекрывать -


Ну, я типа в курсе...  :)


 
Vitaliy_____   (2009-05-22 06:32) [21]

По-моему автор уже все исправил, проверил и возрадовался....
А вот как перевести слово override; можно спорить сколько угодно.
Лингва (10) при выборе компьютерной тематики перевода говорит, что это слово надо понимать
замена, замещение,
    подменять (подмена производным классом виртуальных функций базового класса; (см. тж. polymorphism )

А вот "перекрывать" нигде не встречается. Хотя мне и понятны все варианты, но лингвистика такая штука, что оставим ее для другого форума :)

Всем большое спасибо!



Страницы: 1 вся ветка

Текущий архив: 2009.07.12;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.013 c
2-1242801052
belmol
2009-05-20 10:30
2009.07.12
не понимаю как сделать, где ошибка


2-1242807787
Den1111
2009-05-20 12:23
2009.07.12
Организация поиска "Далее"


2-1242982981
dort12
2009-05-22 13:03
2009.07.12
Проблема с прекреплением attachment


15-1241797779
Копир
2009-05-08 19:49
2009.07.12
А вот, история! Это Вам не Карамзин. Какой-то Анисимов?


2-1242812018
Вася
2009-05-20 13:33
2009.07.12
TTreeView. Пиктограммы