![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
New & Dispose [D5, Win95/98]
Dmitry Toropov © (2002-07-24 18:04:00)Если кому лень особенно напрягать не придется, прошу ответить на следующий вопрос:
использую след. код (схематично):
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]);
Прав тот, у кого больше прав (2002-07-24 19:49:00) [1]2Dmitry Toropov
Нет, не надо. Я погорячился.
Dispose вызовет Finalize сам.
Dmitry Toropov (2002-07-24 19:47:00) [2]2
>p^.pb.Free;
>Dispose(p);
>Это странно. Ошибка не здесь. (И кстати, какая ошибка-то?)
Да, должен принести свои извинения, видимо вчера у меня была в чем-то другом ошибка, и я ее случайно исправил, но подумал, что сработало удаление p^.pb.Free В любом случае, в споре родилась истина (для меня ессно :))
Приношу свои благодарности и извинения
З.Ы.
я так и не понял, надо явно удалять string или нет?
Прав тот, у кого больше прав (2002-07-24 19:46:00) [3]>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 - тогда
без финализации не обойтись.
saxon (2002-07-24 19:37:00) [4]А в чем собсвенно вопрос, то? :)
Прав тот, у кого больше прав (2002-07-24 19:35:00) [5]>Skier © (24.07.02 19:27)
>Нет.
До чего дошёл прогресс... Сейчас проверю.
Skier (2002-07-24 19:31:00) [6]>Прав тот, у кого больше прав
> Это-то ещё зачем? - при разрушении компонент удаляется автоматически
> из списков
Согласен. Поспешил.
Dmitry Toropov (2002-07-24 19:30:00) [7]p^.pb.Free;
Dispose(p);
Это странно. Ошибка не здесь. (И кстати, какая ошибка-то?)
Сейчас попробую снова ситуацию смоделировать ...
Прав тот, у кого больше прав (2002-07-24 19:29:00) [8]2Skier © (24.07.02 19:23)
>Ещё понадобится RemoveComponent.
Это-то ещё зачем? - при разрушении компонент удаляется автоматически из списков Components, Classes своих Owner"a и Parent"a.
Ничего, кроме pb.Free не нужно.
DiamondShark (2002-07-24 19:27:00) [9]>>почему освобождается (и освобождается ли) память pb^ (если
>>можно так выразиться :-)) при Dispose(p).
Строка освободится, если на нее больше нет ссылок
Экземпляр класса останется
Из кучи будет удалено sizeof(Tobj)=8 байт
-----
А аристотели фиговы все теоретизируют, опыт им не нужен.
Skier (2002-07-24 19:27:00) [10]>Прав тот, у кого больше прав
Нет.
Прав тот, у кого больше прав (2002-07-24 19:25:00) [11]>Skier
>Не обязательно, в Delphi есть механизм подсчёта ссылок на String
Он работает, если структура объявлена статически.
> Dmitry Toropov (24.07.02 19:18)
Вдогонку. Если я буду делать
p^.pb.Free;
Dispose(p);
Это странно. Ошибка не здесь. (И кстати, какая ошибка-то?)
Skier (2002-07-24 19:23:00) [12]>Dmitry Toropov
Ещё понадобится RemoveComponent.
Skier (2002-07-24 19:20:00) [13]>Прав тот, у кого больше прав
> тоже надо освобождать - с помощью Finalize(p^);
Не обязательно, в Delphi есть механизм подсчёта ссылок на String
Dmitry Toropov (2002-07-24 19:18:00) [14]Вдогонку. Если я буду делать
p^.pb.Free;
Dispose(p);
это будет ошибкой. Вот в чем я не могу разобраться. Правило, что каждый объект, созданный Create должен быть явно уничтожет я понял. Именно это и вызывает у меня недоумение.
Skier (2002-07-24 19:18:00) [15]>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;
Прав тот, у кого больше прав (2002-07-24 19:17:00) [16]Dmitry Toropov
При Dispose ничего не освобождается, кроме самой памяти, занимаемой структурой.
Менеджер памяти абсолютно в неведении, что находится в этой памяти, есть ли в ней указатели на какие-то внешние объекты, длинные строки и т.д.
Кстати, строку (если это не ShortString) тоже надо освобождать - с помощью Finalize(p^);
Dmitry Toropov (2002-07-24 19:15:00) [17]Вдогонку. Если я буду делать
p^.pb.Free;
Dispose(p);
это будет ошибкой. Вот в чем я не могу разобраться. Правило, что каждый объект, созданный Create должен быть явно уничтожет я понял. Именно это и вызывает у меня недоумение.
Skier (2002-07-24 19:13:00) [18]>Dmitry Toropov
В Dispose(p) созданный объект не освободится !
Будет баааааальшой memory leak !
Dmitry Toropov (2002-07-24 19:09:00) [19]Да, здесь я согласен. Но. После New(p) отводится память для ссылки на строку и фактической строки, поскольку в Delphi это реализовано на уровне языка, но ProgressBar-то не создается автоматически, я же его создал Create"ом! И весь вопрос в том, почему освобождается (и освобождается ли) память pb^ (если можно так выразиться :-)) при Dispose(p). Т.е. то, что место под ссылку освободится - это ясно, но как освободится сам экземпляр объекта ProgressBar, если я не вызываю pb^.Free? That"s the question.
Прав тот, у кого больше прав (2002-07-24 19:06:00) [20]В дельфи все переменные объектного типа
obj: TSomeObject
являются по сути замаскированными указателями на объект.
(За исключением объектов старого типа)
Поэтому в структуре полем является указатель на объект (TProgressBar), размер коего - 4 байта.