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

Вниз

New & Dispose   Найти похожие ветки 

 
Dmitry Toropov   (2002-07-24 18:04) [0]

Если кому лень особенно напрягать не придется, прошу ответить на следующий вопрос:
использую след. код (схематично):

Pobj = ^Tobj;
Tobj = record
ph:TProgressBar;
s:string;
end;

Tlst =class( TList )
public
function Add(t:Pobj):integer;override;
destructor Destroy;
...
property Items[index:integer]:Pobj read GetIndex write PutIndex;
end;

в форме в OnCreate:
lst:=TList.Create;

добавляю в список:
...
var
p:Pobj;
begin
New(p);
p^.pb:=TProgressBar.Create(frmMain);
p^.pb.Parent:=frmMain;
lst.Add(p);

в OnDestroy формы:
lst.Free;

теперь, (кто дотерпел :))), собственно вопрос:
почему (теоретически объяснить) это работает:

destructor Destroy;
var
i:integer;
begin
for i:=0 to lst.Count-1 do begin
Dispose(Items[i]);
end;
end;

т.е., почему мне не надо делать
Items[i]^.pb.Free; //?
перед Dispose(Items[i]);


 
Skier ©   (2002-07-24 18:21) [1]

>Dmitry Toropov
Вообще-то все твои ProgressBar-ы освободит форма при своём
уничножении (хотя всё это не есть хорошо).



> почему (теоретически объяснить) это работает:
>
> destructor Destroy;
> var
> i:integer;
> begin
> for i:=0 to lst.Count-1 do begin
> Dispose(Items[i]);
> end;
> end;


А почему (как тебе кажется) это не должно работать ?


 
Dmitry Toropov   (2002-07-24 18:41) [2]

То, что форма освободит - это ясно, но я динамически создаю потоки, которые взаимодействуют с progress bar"ами и их нужно бы удалять самостоятельно по мере прекращения соответствующих потоков.
Не очень понимаю, что делает TProgressBar.Create.
Получается, что когда я делаю New(p), я уже отвожу место на куче для p^.pb(progress bar"a).
В принципе, вопрос сводится именно к тому, что же делает Create.


 
Skier ©   (2002-07-24 18:45) [3]

>Dmitry Toropov
TProgressBar.Create создаёт экзепмляр класса в памяти.



> Получается, что когда я делаю New(p), я уже отвожу место
> на куче для p^.pb(progress bar"a).


Ничего подобного !
Ты отводишь место только для указателя
(p^.pb - 4 байта) на экземпляр класса, который ты ДОЛЖЕН создать через TProgressBar.Create.


 
Dmitry Toropov   (2002-07-24 18:53) [4]

из Help"а:
The New procedure creates a new dynamic variable and sets a pointer variable to point to it. P is a variable of any pointer type. The size of the allocated memory block corresponds to the size of the type that P points to. The newly created variable can be referenced as P^.
Поэтому, я думаю что динамическая память отводится именно для record со всеми ее полями ( string, TProgressBar и т.д.).
Так прав я или не прав?


 
Skier ©   (2002-07-24 19:00) [5]

>Dmitry Toropov


> Так прав я или не прав?


ТЫ НЕПРАВ !!!

Попробуй убери строку p^.pb:=TProgressBar.Create(frmMain);
и обратись к p^.pb как к объекту.
И сразу увидишь как "память отводится именно для record со всеми ее полями"

Пробуй...


 
Anatoly Podgoretsky ©   (2002-07-24 19:04) [6]

Каждый созданный объект Create должен быть освобожден Free
Каждый выделенный блок памяти New должен быть возвращен Dispose


 
Прав тот, у кого больше прав   (2002-07-24 19:06) [7]

В дельфи все переменные объектного типа
obj: TSomeObject
являются по сути замаскированными указателями на объект.
(За исключением объектов старого типа)

Поэтому в структуре полем является указатель на объект (TProgressBar), размер коего - 4 байта.


 
Dmitry Toropov   (2002-07-24 19:09) [8]

Да, здесь я согласен. Но. После New(p) отводится память для ссылки на строку и фактической строки, поскольку в Delphi это реализовано на уровне языка, но ProgressBar-то не создается автоматически, я же его создал Create"ом! И весь вопрос в том, почему освобождается (и освобождается ли) память pb^ (если можно так выразиться :-)) при Dispose(p). Т.е. то, что место под ссылку освободится - это ясно, но как освободится сам экземпляр объекта ProgressBar, если я не вызываю pb^.Free? That"s the question.


 
Skier ©   (2002-07-24 19:13) [9]

>Dmitry Toropov
В Dispose(p) созданный объект не освободится !
Будет баааааальшой memory leak !


 
Dmitry Toropov   (2002-07-24 19:15) [10]

Вдогонку. Если я буду делать
p^.pb.Free;
Dispose(p);

это будет ошибкой. Вот в чем я не могу разобраться. Правило, что каждый объект, созданный Create должен быть явно уничтожет я понял. Именно это и вызывает у меня недоумение.


 
Прав тот, у кого больше прав   (2002-07-24 19:17) [11]

Dmitry Toropov
При Dispose ничего не освобождается, кроме самой памяти, занимаемой структурой.
Менеджер памяти абсолютно в неведении, что находится в этой памяти, есть ли в ней указатели на какие-то внешние объекты, длинные строки и т.д.

Кстати, строку (если это не ShortString) тоже надо освобождать - с помощью Finalize(p^);


 
Skier ©   (2002-07-24 19:18) [12]

>Dmitry Toropov

Попробуй так :


Tobj = record
ph:TProgressBar;
s:string;
end; //Tobj
Pobj = ^Tobj;

Tlst = class(TList)
protected
procedure Put(Index: Integer; Item: PObj);
function Get(Index: Integer): PObj;
public
function AddNewItem(const AStr : string;
AOwner : TComponent ; AParent : TWinControl) : Integer;
destructor Destroy; override;
property Items[index : Integer] : PObj read Get write Put;
default;
end; //Tlst


{ Tlst }

function Tlst.AddNewItem(const AStr: string; AOwner: TComponent;
AParent: TWinControl): Integer;
var
Aobj : Pobj;
begin
Aobj := AllocMem(SizeOf(Tobj));
with Aobj^ do begin
s := AStr;
ph := TProgressBar.Create(AOwner);
ph.Parent := AParent;
end; //with
Result := inherited Add(Aobj);
end;

destructor Tlst.Destroy;
var
ii : Integer;
begin
for ii := 0 to Count - 1 do begin
if Items[ii] = nil then Continue;
with Items[ii]^ do begin
if ph <> nil then FreeAndNil(ph);
end; //with
FreeMem(Items[ii], SizeOf(Tobj));
end; //for
inherited Destroy;
end;

function Tlst.Get(Index: Integer): PObj;
begin
Result := inherited Get(Index);
end;

procedure Tlst.Put(Index: Integer; Item: PObj);
begin
inherited Put(Index, Item);
end;


 
Dmitry Toropov   (2002-07-24 19:18) [13]

Вдогонку. Если я буду делать
p^.pb.Free;
Dispose(p);

это будет ошибкой. Вот в чем я не могу разобраться. Правило, что каждый объект, созданный Create должен быть явно уничтожет я понял. Именно это и вызывает у меня недоумение.


 
Skier ©   (2002-07-24 19:20) [14]

>Прав тот, у кого больше прав


> тоже надо освобождать - с помощью Finalize(p^);


Не обязательно, в Delphi есть механизм подсчёта ссылок на String


 
Skier ©   (2002-07-24 19:23) [15]

>Dmitry Toropov
Ещё понадобится RemoveComponent.


 
Прав тот, у кого больше прав   (2002-07-24 19:25) [16]

>Skier

>Не обязательно, в Delphi есть механизм подсчёта ссылок на String
Он работает, если структура объявлена статически.

> Dmitry Toropov (24.07.02 19:18)
Вдогонку. Если я буду делать
p^.pb.Free;
Dispose(p);

Это странно. Ошибка не здесь. (И кстати, какая ошибка-то?)


 
Skier ©   (2002-07-24 19:27) [17]

>Прав тот, у кого больше прав
Нет.


 
DiamondShark ©   (2002-07-24 19:27) [18]

>>почему освобождается (и освобождается ли) память pb^ (если
>>можно так выразиться :-)) при Dispose(p).

Строка освободится, если на нее больше нет ссылок
Экземпляр класса останется
Из кучи будет удалено sizeof(Tobj)=8 байт

-----

А аристотели фиговы все теоретизируют, опыт им не нужен.


 
Прав тот, у кого больше прав   (2002-07-24 19:29) [19]

2Skier © (24.07.02 19:23)
>Ещё понадобится RemoveComponent.

Это-то ещё зачем? - при разрушении компонент удаляется автоматически из списков Components, Classes своих Owner"a и Parent"a.

Ничего, кроме pb.Free не нужно.


 
Dmitry Toropov   (2002-07-24 19:30) [20]

p^.pb.Free;
Dispose(p);

Это странно. Ошибка не здесь. (И кстати, какая ошибка-то?)

Сейчас попробую снова ситуацию смоделировать ...


 
Skier ©   (2002-07-24 19:31) [21]

>Прав тот, у кого больше прав

> Это-то ещё зачем? - при разрушении компонент удаляется автоматически
> из списков

Согласен. Поспешил.


 
Прав тот, у кого больше прав   (2002-07-24 19:35) [22]

>Skier © (24.07.02 19:27)
>Нет.

До чего дошёл прогресс... Сейчас проверю.


 
saxon ©   (2002-07-24 19:37) [23]

А в чем собсвенно вопрос, то? :)


 
Прав тот, у кого больше прав   (2002-07-24 19:46) [24]

>saxon © А какая, собственно, разница.

>Skier © (24.07.02 19:27)
Да, ты был прав. После вызова Dispose счетчик ссылок строки уменьшается.

Собственно, Dispose сам вызывает Finalize:

procedure _Dispose{ p: Pointer; typeInfo: Pointer};
asm
PUSH EAX
CALL _Finalize
POP EAX
CALL _FreeMem
end;


Но если бы память выделялась через GetMem или ReallocMem - тогда
без финализации не обойтись.


 
Dmitry Toropov   (2002-07-24 19:47) [25]

2
>p^.pb.Free;
>Dispose(p);

>Это странно. Ошибка не здесь. (И кстати, какая ошибка-то?)

Да, должен принести свои извинения, видимо вчера у меня была в чем-то другом ошибка, и я ее случайно исправил, но подумал, что сработало удаление p^.pb.Free В любом случае, в споре родилась истина (для меня ессно :))
Приношу свои благодарности и извинения

З.Ы.
я так и не понял, надо явно удалять string или нет?



 
Прав тот, у кого больше прав   (2002-07-24 19:49) [26]

2Dmitry Toropov

Нет, не надо. Я погорячился.
Dispose вызовет Finalize сам.



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

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

Наверх




Память: 0.53 MB
Время: 0.012 c
7-13839
Jet_vrn
2002-05-17 19:04
2002.08.05
Как ускорить рисование на канве?


1-13604
иван
2002-07-24 16:58
2002.08.05
ПОМОЖИТЕ, ЧЕМ МОЖИТЕ!!!!!!!!


6-13754
neodiX
2002-05-24 18:01
2002.08.05
TClientSocket and TServerSocket


1-13646
Kudatsky
2002-07-22 10:13
2002.08.05
Delphi 5 не реагирует на ошибки с плавающей точкой


4-13863
Alexec
2002-05-18 11:54
2002.08.05
Процессы