Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.03.27;
Скачать: [xml.tar.bz2];

Вниз

Запутался с интерфейснымми ссылками   Найти похожие ветки 

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.008 c
3-87867
Anonimus
2003-03-11 10:27
2003.03.27
Потеря данных


6-88121
Керик
2003-01-25 19:02
2003.03.27
Отключение от инета


1-88058
tim5
2003-03-15 13:36
2003.03.27
Удаление файлов.


3-87795
SATAN aka NAPALM
2003-03-07 13:15
2003.03.27
Базы Данных


1-88025
NAlexey
2003-03-14 13:46
2003.03.27
Как динамически менять класс элемента





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский