Форум: "Основная";
Текущий архив: 2002.08.05;
Скачать: [xml.tar.bz2];
Вниз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;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.006 c