![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как корректно уничтожить из дестрактора компоненты ScrollBar
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.