Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.01.10;
Скачать: [xml.tar.bz2];




Вниз

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


Aleksandr   (2001-12-21 14:33) [0]

Компонента имеет 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...
Чего я не так делаю?



Alx2   (2001-12-21 14:39) [1]

Может, его кто-то уже перед этим прибил?



Aleksandr   (2001-12-21 14:41) [2]

Не знаю... Только если этот самый Parent раньше не вышибает СкроллБар, а уж потом компоненту... Только как проверить, если Assigned всего лишь сверяет с nil?



Alx2   (2001-12-21 14:44) [3]

Вот-вот...
Тогда просто его не грохай. Это сделает Owner, когда помирать будет (или Parent? - не помню. Но ведь позаботился кто-то уже?).



Alx2   (2001-12-21 14:46) [4]

Вдогонку: в конструктор скроллу попробую передавать себя (т.е TWay).



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

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



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

Спасибо!



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

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



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

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



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

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



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

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

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 вызываю последним...



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

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



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

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



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

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

FScrollBar:=TScrollBar.Create(AOwner);

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

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

FScrollBar:=TScrollBar.Create(Self);

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



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

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



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

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



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


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



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

> Alx2

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

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


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

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



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

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



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

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



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

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

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

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



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

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



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

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

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



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

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



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

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




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.01.10;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.76 MB
Время: 0.062 c
3-28435           AlexNord              2001-12-10 06:08  2002.01.10  
BatchMove


7-28550           Eduard1               2001-09-28 14:04  2002.01.10  
Hook - Help me


3-28416           Atrem                 2001-11-30 19:35  2002.01.10  
BLOB поля


6-28523           Dr. Web               2001-10-03 10:34  2002.01.10  
Фильтрация IP пакетов...


1-28498           Dimedrol              2001-12-22 13:30  2002.01.10  
DLL вызывает процедуру в основной проге...