Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.64 MB
Время: 0.036 c
3-13569
jim
2002-07-16 12:55
2002.08.05
Обновление через ClientDataSet нескольких таблиц


1-13672
tovSuhov
2002-07-23 16:20
2002.08.05
EditMask


4-13857
Vaddya
2002-05-29 21:16
2002.08.05
Смена


3-13561
AM
2002-07-16 09:16
2002.08.05
мастер – таблица


14-13816
111
2002-07-11 18:41
2002.08.05
HiperTerminal





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский