Текущий архив: 2003.03.27;
Скачать: CL | DM;
ВнизЗапутался с интерфейснымми ссылками Найти похожие ветки
← →
oomneeq (2003-03-13 14:31) [0]имеем
type
IMyInterface=interface
end;
TMyComp=class(TComponent,IMyInterface)
end;
TMyForm=class(TForm)
private
FILink: IMyInterface
public
// constructor Create(AOwner:TComponent);
end;
procedure Test;
var MF:TMyForm;
begin
MF:=TMyForm.Create(nil);
with MF do begin
FILink:=TMyComp.Create(MF);
Showmodal;
//block1
//надо ли тут чтото делать с FILink
//например FILink:=nil;
//по идее, объект, созданный с помощью FILink
//будет уничтожен самой формой-владельцем (MF)
Free;
end; // with
//block2
//а вот тут, при выходе, я предполагаю, что дельфи делает попытку
//очистить FILink как любую интерфейсную ссылку.
//но объект то уже уничтожен, и случается AV (через раз)
//в System._IntfClear
end;
end;
_Addref и _Release не переопределены, т.е. испльзуются
TComponent"ские методы, возврщающие в данном случае -1 всегда
Действительно ли мое предположение по поводу Block2
и надо ли садить на nil FILink в Block1 ??
Научите плиз, мастера, как грамотно здесь поступать
← →
oomneeq (2003-03-13 14:44) [1]Я тут немного подумал, и решил уточнить вопрос;
cчитается ли выход из процедуры Test выходом и з области видимости для переменной FILink?
Ведь это не локальная переменная, а поле уже уничтоженногоо
объекта!
← →
Smithson (2003-03-13 14:54) [2]Где-то я читал, что IUnknow по умолчанию в VCL не реализован. То бишь тебе надо их делать.
← →
viajero (2003-03-13 15:35) [3]TComponent действительно имеет весьма специфическую реализацию
IUnknow:
function TComponent.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if FVCLComObject = nil then
begin
if GetInterface(IID, Obj) then Result := S_OK
else Result := E_NOINTERFACE
end
else
Result := IVCLComObject(FVCLComObject).QueryInterface(IID, Obj);
end;
function TComponent._AddRef: Integer;
begin
if FVCLComObject = nil then
Result := -1 // -1 indicates no reference counting is taking place
else
Result := IVCLComObject(FVCLComObject)._AddRef;
end;
function TComponent._Release: Integer;
begin
if FVCLComObject = nil then
Result := -1 // -1 indicates no reference counting is taking place
else
Result := IVCLComObject(FVCLComObject)._Release;
end;
Если ты хочешь иметь стандартное поведение интерфейса,
тебе придётся переопределить_Addref и _Release, а так же QueryInterface a la TInterfacedObject.
← →
viajero (2003-03-13 15:36) [4]Пардон, QueryInterface менять не надо
← →
vedmed (2003-03-13 16:14) [5]При выходе из процедуры в block2 вызывается метод _Release уже не существующего объекта, отсюда и AV. Присвоение nil в block1 в данном случае должно решить проблему, т. к. вызов _Release для объектов равных nil не производиться.
← →
icWasya (2003-03-13 16:35) [6]
> vedmed © (13.03.03 16:14)
> При выходе из процедуры в block2 вызывается метод _Release
> уже не существующего объекта, отсюда и AV. Присвоение nil
> в block1 в данном случае должно решить проблему, т. к. вызов
> _Release для объектов равных nil не производиться.
ничего не вызывается, поскольку область видимости
FILink - весь объект TMyForm
, и FILink будет уничтожен только в деструкторе TMyForm
← →
REA (2003-03-13 16:46) [7]ИМХО проще перегрузить и оттрассировать откуда что вызывается, но по логике форма удаляет объект, а счетчик ссылок не используется.
← →
vedmed (2003-03-13 16:56) [8]2 icWasya
действительно, не заметил 8-(
← →
oomneeq (2003-03-13 17:23) [9]>Smithson © (13.03.03 14:54)
>Где-то я читал, что IUnknow по умолчанию в VCL не реализован. То бишь тебе надо их делать.
Кого "их"?
IUnknow не реализован, но все к этому подготовлено, т.е. все три метода реализованы, viajero их тут нарисовал.
Я тут погонял тест.
Похоже дело еще круче.
>icWasya © (13.03.03 16:35)
>ничего не вызывается, поскольку область видимости
>FILink - весь объект TMyForm
похоже на то, т.к. AV cлучается до входа в block2 - т.е. во Free.
(я дописал выполняемую строчку сразу за Free и поставил брекпойнт на нее) так вот - AV случается не доходя до этой точки
Вопрос теперь такой:
если область видимости FILink - весь объект TMyForm то
что в таком случае считается выходом из зоны. точнее сказать в какой момент вызывается уборщик? При выходе из TObject.Destroy ?
Я предполагаю, что как минимум после освобождения всех подчиненных компонентов - один из которых создан с помощью FILink
т.е. когда доходит дело чистить FILink, то форма-владелец у же грохнула всех владеемых и компонент, на который переменная FILink все еще указывает, уже уничтожен, но чистку уже не остановить, вот и AV.
Ну вот, сам себе все и рассказал.
Опровержения и подтверждения принимаются.
Что происходит раньше при уничтожении формы - освобождение всех подчиненных компонентов или очистка интерфейсных ссылок
← →
icWasya (2003-03-13 18:07) [10]
> Что происходит раньше при уничтожении формы - освобождение
> всех подчиненных компонентов или очистка интерфейсных ссылок
очистка интерфейсных ссылок скорее всего происходит в TObject.Destroy,
освобождение всех подчиненных компонентов происходит раньше - в TComponent.Destroy
← →
icWasya (2003-03-13 18:13) [11]а вообще говоря не рекомендуется смешивать работу через интерфейсы и через компоненты
← →
REA (2003-03-13 18:21) [12]Дык может его создать в конструкторе формы, а занилить в деструкторе, а то получается, что уничтожается используемый еще объект. Надеюсь заниливание не приведет к его уничтожению, поскольку подсчет ссылок не реализован.
← →
Serginio (2003-03-13 18:23) [13]Сделай
TMyForm=class(TForm,IMyInterface)
private
public
// constructor Create(AOwner:TComponent);
end;
TMyForm.Create(nil) As IMyInterface;
← →
vuk (2003-03-13 18:24) [14]>что в таком случае считается выходом из зоны.
Разрушение экземпляра. см. в system: _ClassDestroy, TObject.FreeInstance, TObject.CleanupInstance
>Что происходит раньше при уничтожении формы - освобождение всех
>подчиненных компонентов или очистка интерфейсных ссылок
Сначала происходит удаление компонентов. Финализация делается в самую последнюю очередь.
В принципе решить Вашу проблему можно несколькими способами:
1. Принудительно очистить FILink в Test
2. Если в TMyComp перекрыты _AddRef и _Release, так, что подстчет ссылок всё-таки делается, то можно не делать форму владельцем экземпляра компонента.
← →
oomneeq (2003-03-13 18:59) [15]Радует ваша отзывчивость. Спасибо всем.
>icWasya © (13.03.03 18:13)
а вообще говоря не рекомендуется смешивать работу через интерфейсы и через компоненты
Да вообще я про это читал. Только наверно не врубаюсь.
Ты не мог бы сказать, где конкретно в вышеуказанном примере
происходит смешивание?
и еще к тому же - правильно ли я мыслю, что смешивание (допустим я разобрался что это такое :-) ) чревато боком только в случаях когда подсчет ссылок реализован, и безопасно, если не реализован.
>Serginio (13.03.03 18:23)
Ваще не понял, о чем ты. В примере интерфейс реализует ведь не форма, а TMyComp ?!
2vuk
>1. Принудительно очистить FILink в Test
cпасибо, я как раз так и делаю, просто теперь уже осознанно :=)
>2. Если в TMyComp перекрыты _AddRef и _Release, так, что подстчет ссылок всё-таки делается, то можно не делать форму владельцем экземпляра компонента
Сдается мне, что если не делать форму владельцем, и перекрыты
_AddRef и _Release, так, что подстчет ссылок всё-таки делается,
то FILink:=nil не только обнулит указатель, но еще и уничтожит объект, как это и заведено у интерфейсных ссылок.
т.е. получается по любому FILink:=nil есть благо в случаях сомнения.
← →
vuk (2003-03-13 19:19) [16]>т.е. получается по любому FILink:=nil есть благо в случаях
>сомнения.
Ну... В одном случае это необходимо, а в другом используется просто как "контрольный в голову".
← →
Serginio (2003-03-13 19:21) [17]У тебя сначала уничтожается TMyComp
а ссылка в TMyForm остается.
делай в TMyComp.Destroy
(Owner as TMyForm).ILink:=nil;
← →
icWasya (2003-03-13 19:37) [18]>где конкретно в вышеуказанном примере
происходит смешивание?
когда работаешь с TMyForm как с компонетом -
TMyForm.Create(Self)
компоненты сами по себе записываются к кучу списков и удаляются из них при собственном уничтожении, причем деструкторы вызываются явно.
когда работаешь через интерфейсы, при автоматическом подсчёте ссылок объект уничтожается только при обнулении счётчика ссылок на него, а при явном вызове деструктора объект может быть уничтожен , а все ссылки останутся со всеми вытекающими...
← →
Serginio (2003-03-13 19:38) [19]Вернее в TMyForm.Destroy
FILink:=nil;
inherited Destroy;
← →
oomneeq (2003-03-13 19:55) [20]>icWasya © (13.03.03 19:37)
Ок, проясняется. Применительно к примеру, потенциальные грабли в том, что созданый через интерфейсную ссылку объект включается в список Сomponents, каждый элемент которого подлежащит явному уничтожению (читай-явному вызову Destroy) что не есть логично для таким образом создаваемых объектов.
Ну вот, день не зря прошел....:)
Страницы: 1 вся ветка
Текущий архив: 2003.03.27;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.008 c