Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как корректно уничтожить из дестрактора компоненты ScrollBar


Страницы:   1 2

Aleksandr ©   (2001-12-21 14:33:00) 

Компонента имеет ScrollBar, создающийся при ее создании:
constructor TWayTree.Create(AOwner : TComponent);
begin
Inherited;
FScrollBar:=TScrollBar.Create(AOwner);
FScrollBar.Parent:=Parent;
FScrollBar.OnScroll:=FWayTreeScroll;
...
end;
Parent ScrollBar"у я назначаю, чтобы он не мигал и не дергался при перерисовке компоненты (и вообще ей жить не мешал). То есть фактически он не принадлежит компоненте, просто скроллирует ее.
Все прекрасно, но при вызове дестрактора компоненты в этом месте:
if Assigned(FScrollBar) then
FScrollBar.Free
появляется Access Violation at 00000000...
Чего я не так делаю?


Юрий Зотов   (2001-12-21 20:57:00) [1]

Если его Owner - не nil, то он будет уничтожен вместе с Owner"ом. Но лично я предпочитаю удалять ручками, в деструкторе - как у Вас. Хотя бы потому, что это позволяет вылавливать ситуации, подобные Вашей и указывающие на то, что в программе явно что-то не так. Поэтому очень советую Вам все же раскопать, в чем там дело.


Aleksandr   (2001-12-21 17:34:00) [2]

ОК. А если его вообще не уничтожать в дестракторе, он так и будет память загаживать? Просто формой с этой компонентой юзверы будут пользоваться с такой же частотой, с какой бухгалтер юзает калькулятор...


Юрий Зотов   (2001-12-21 17:08:00) [3]

Тогда, видимо, Alx2 прав - надо искать, где убивается Scrollbar. Сделайте так.

1. Проверьте, чтобы в путь отладки были включены исходники VCL.
2. В деструкторе TScrollbar поставьте BreakPoint и запустите программу.
3. Когда придете на BreakPoint, вызовите окно Call Stack и посмотрите, откуда Вы туда пришли. Скорее всего, там и будет причина ошибки.


Aleksandr   (2001-12-21 17:06:00) [4]

Да, кстати, в дестракторе я FScrollBar.Free заменил на FreeAndNil(FScrollBar) - на случай, если AV генерирует Owner.


Aleksandr   (2001-12-21 17:01:00) [5]

Перепробовал варианты в констракторе:

FScrollBar:=TScrollBar.Create(Self);
FScrollBar:=TScrollBar.Create(Owner);

При любом из них в Destroy происходит AV.


Юрий Зотов   (2001-12-21 16:49:00) [6]

> Alx2 © (21.12.01 16:29)
Согласен, нужен код конструктора - тот, который сейчас, а не тот, который уже приводился. Впрочем, подозреваю, что он не изменился, иначе ошибка должна была исчезнуть. Странно, что Aleksandr молчит. Ау-у-у!


Alx2   (2001-12-21 16:29:00) [7]

>Юрий Зотов
Ну ладно. Александр нас рассудит. В своих ответах ранее я сделал акцент именно на то, чтобы у скролла Owner был именно TWayTree. Как оно у него стало на самом деле - не знаю. То есть вызов должен быть именно такой, какой написали Вы: FScrollBar:=TScrollBar.Create(Self);
Но то, что ошибка не исчезла - странно. Хотя без исходников сказать мало что можно.


Юрий Зотов   (2001-12-21 16:22:00) [8]

> Alx2

> где этот скролл помереть успевает до TWayTree.Destroy

Нигде. До TWayTree.Destroy он не умирает. Он умирает именно в TWayTree.Destroy.


> так как Owner у него TWayTree...

Нет. Owner у него ТОТ ЖЕ, что и у TWayTree. В этом и есть ошибка. Сначала его убивает TWayTree, а потом еще и Owner - и вот здесь-то возникает AV. То есть, НЕ в TWayTree.Destroy, а уже ПОСЛЕ.


Freezer   (2001-12-21 16:20:00) [9]


if not (csDestroying in ComponentState) then
if Assigned(FScrollBar) then
FScrollBar.Free;
inherited Destroy;


Alx2   (2001-12-21 16:11:00) [10]

>Юрий Зотов
Процитирую себя (см. выше):
Вдогонку: в конструктор скроллу попробуй передавать себя (т.е TWaytree).
Сейчас вся беда в выяснении где этот скролл помереть успевает до TWayTree.Destroy, так как Owner у него TWayTree...


Alx2   (2001-12-21 16:08:00) [11]

>DieHard
Оно-то понятно. Просто интересно где этот скролл помереть успевает до TWayTree.Destroy, так как Owner у него TWayTree...


Юрий Зотов   (2001-12-21 16:06:00) [12]

Происходит следующее. Scrollbar Вы создаете с тем же владельцем, что и владелец Вашего компонента:

FScrollBar:=TScrollBar.Create(AOwner);

Значит, этот AOwner при своем уничтожении будет убивать сначала Ваш компонент, а потом созданный Вами Scrollbar. Но Ваш компонент убивает его в своем деструкторе и поэтому Aowner пытается убить уже убитый Scrollbar. Вот и ошибка.

Создавайте Scrollbar так:

FScrollBar:=TScrollBar.Create(Self);

И после этого можете убивать его в своем деструкторе (а можете и не убивать - он будет убит автоматически).


Alx2   (2001-12-21 16:05:00) [13]

Попробуй проверить у TWay свойство ComponentCount
Если 0, то все где-то прибито уже.


DieHard   (2001-12-21 15:58:00) [14]

Зачем вообще разрушаешь FScrollBar, предоставь это AOwner, кому и положено...


Aleksandr   (2001-12-21 15:51:00) [15]

Полностью дестрактор выглядит так:

destructor TWayTree.Destroy;
var
W : TWayItem;
begin
try
if FDestroyItems then begin
while FPoints.Count>0 do begin
W:=TWayItem(FPoints.Items[0]);
FPoints.Delete(0);
W.Free
end
end;
finally
FPoints.Free;
FFont.Free;
if Assigned(FScrollBar) then
FScrollBar.Free;
inherited Destroy
end
end;

Естественно, inherited Destroy вызываю последним...


Alx2   (2001-12-21 15:27:00) [16]

Петрушка может сидеть, наверное, в том, что в TWay.Destroy сначала идет inherited, который и грохает скролл. Т.е. заботится уже не о ком.
Можно попробовать для чистоты inherited воткнуть последним, после FScrollBar.Free; FScrollBar:=Nil. И посмотреть где будет AV.


Alx2   (2001-12-21 15:23:00) [17]

Как выглядит код сейчас?


Aleksandr   (2001-12-21 15:16:00) [18]

Млин... усе равно Access Violation...


Aleksandr   (2001-12-21 15:06:00) [19]

Спасибо!


Alx2   (2001-12-21 14:49:00) [20]

Точно!
Вот из help:
property Owner : TComponent;
Indicates the component that is responsible for freeing this component.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо