![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Удаление интерфейсных объектов [D6, Win2k]
masik © (2002-04-22 17:21:00)господа, есть набор интерфейсов и классов, которые их реализует. Естественно возникает вопрос корректного удаления этих классов. Как я понимаю Дельфя удаляет их раньше чем я. Как это можно отследить.
Suntechnic (2002-04-24 05:49:00) [1]Fantasist (24.04.02 02:42)
Конечно не измениться. Просто если ты назавешь паравоз параходом, то остальные могут не понять, то ли ты не видишь разницы между параходом и паравозом, то ли тебе просто вздумалось поиграть словами.
Да чего ты пристал к человеку. "Область видимости" и "область действия" это одно и тоже (scope по-английски как тут уже правильно заметили). И смысл в эти понятия вкладывается одинаковый. Среди С-шников так вообще я употребление "область действия" и не слышал никогда. Всегда говорят "область видимости", а что там принято среди Делфистов вам видней :). Так что зря ты человеку про параходы рассказывал :)
Fantasist (2002-04-24 02:42:00) [2]
> Как видно, использование переменных типа интерфейс (внутри
> - это указатель), приводит к автоматическому отслеживанию
> ссылок.
Именно по этому, когда я хочу све держать под своим контролем, вместо интерфейсов использую классы. Типа так:
TInterface=class
QueryInterface(ID:TGUID; out Obj); virtual;
AddRef; virtual;
Release; virtual;
end;
Работа не отличается от работы с интерфейсом. Это может не всегда удобно и не всегда нужно, однако позволяет избавиться от навязчивой помощи Delphi, которая не всегда кстати.
> Хотя "ссылка" - все-таки правильнее, переменная типа интерфейс
> - это именно указатель, когда эта переменная выходит из
> области видимости (или ей присваивается другое значение),
> компилятор вызывает release, что уменьшет счетчик ссылок.
Да, это указатель, и уже поэтому я не люблю называть это "ссылкой", ибо это не всегда одно и тоже. Опять же я не соглашусь с этой фразой: "переменная выходит из области видимости ... компилятор вызывает release" так как "область видимости переменной" означает на мой взгляд, совсем не область, где она сохраняет свое значение (то, что Вы, видимо, имеете ввиду).
> Автоматический подсчет ссылок завязан именно на переменные.
>
Безусловно. Я имел ввиду, что там не говорилось о области видимости перемнных типа интерфейс.
> kull © (23.04.02 10:53)
> Ну не область видимости... Назовите как угодно смысл не
> изменится.
Конечно не измениться. Просто если ты назавешь паравоз параходом, то остальные могут не понять, то ли ты не видишь разницы между параходом и паравозом, то ли тебе просто вздумалось поиграть словами.
Krok (2002-04-23 16:39:00) [3]Может, я ошибаюсь, но Release() вроде бы вызывается при присвоении nilэтому указателю(если он указывал на объект). Вот тут-то и можно поймать выгрузку компонента
vuk (2002-04-23 16:29:00) [4]>Поэтому обычно стараются не смешивать объектные и интерфейсные
>ссылки.
При этом, как всегда, действует замечательное правило - если очень хочется и есть точное представление о том, что при этом происходит, то пользоваться вполне можно и ошибок не возникает. Просто нужно с интерфейсными ссылками обращаться так же как и с обычными объектными ссылками, потому как возникающие проблемы примерно того же рода, что и проблемы, например, с обращением к уже удаленному экземпляру при работе с обычными объектами.
Бурундук (2002-04-23 12:31:00) [5]2Fantasist
>Совершенно верно, но если не использовать TInterfacedObject(или
>его собственную реализацию) как предка, то вообще никаких
>проблем с тем, что "Делфи удаляет объект раньше чем я" не
>будет, как было указанно в вопросе.
Это верно, но вполне может возникнуть ситуация, когда
"Делфи захочет удалить объект ПОЗЖЕ чем я"
procedure Proc;
var intf: IMyInterface;
obj: TMyObject;
begin
obj := TMyObject.Create;
obj.GetInterface(IMyInterface, intf);
obj.Free;
// автоматически вызвается inft.Release;
// даже если он ничего не делает (просто возвращает -1), всё равно имеем AV
// т.к. он вызывается через vtable объекта, которого уже нет.
end;
Поэтому обычно стараются не смешивать объектные и интерфейсные ссылки.
Или обеспечить короткую жизнь интерфейсным ссылкам – запросил у объекта, использовал, освободил (Не храня для дальнейшего использования).
vuk (2002-04-23 10:59:00) [6]to Fantasist:
Ну да, скорее область действия.
>объект автоматически удалиться, когда последняя ссылка на него
>выйдет из области видимости.
>Ни слова об области видимости переменных.
Автоматический подсчет ссылок завязан именно на переменные. Компилятор вставляет код финализации интерфейсной переменной как раз тогда, когда поток управления будет выходить из области действия этой переменной - при выходе из процедуры, где она объявлена или куда была передана в качестве параметра а также в деструкторе класса, в котором такая переменная объявлена как член класса.
>Господа, а если я вообще не использую переменных
Если Вы вообще не запрашиваете интерфейсы у объекта, то подсчет ссылок не работает и никак не влияет на функционирование. Если же Вы в одном месте используете экземпляр обычным образом, а в другом запрашиваете у него интерфейсы, то Вам нужно либо переопределить механизм подсчета ссылок, либо в первом случае завести дополнительную интерфейсную ссылку - как раз для того, чтобы контролировать время жизни экземпляра.
>И еще а если интрерфейсов несколько...
Во про количество реализуемых интерфейсов или о чем? Если о количестве, то оно никак не влияет на счетчик ссылок. Влияние оказывают только запросы интерфейсов.
kull (2002-04-23 10:53:00) [7]Ну не область видимости... Назовите как угодно смысл не изменится.
kull (2002-04-23 10:51:00) [8]
> Ни слова об области видимости переменных.
Вызываем Help набираем слово scope:
- "и пусть тот первый бросит в меня камень кто скажет что это - девочка"
Если это не облась видимости или действия идентификатора (называйте хоть чем смысл не изменится), то что это тогда?
procedure P1;
var
it:IInterface; //то что я слышал - область видимости этой переменной - это область где это символическое имя имеет один и тот же смысл.
begin
...
P2;
...
end;
procedure P2;
begin
... //здесь переменная it не видна. В том смысле, что символическое имя it здесь не опеределенно.
end;
Ну а так:
procedure P1;
var
it:IInterface;
begin
...
P2;
...
end;
procedure P2(const I: IInterface);
begin
...
end;
Romkin (2002-04-23 10:45:00) [9]2Fantasist Это можно перевести ..объект автоматически удалиться, когда последнее упоминание о нем выйдет из области видимости...
Хотя "ссылка" - все-таки правильнее, переменная типа интерфейс - это именно указатель, когда эта переменнаявыходит из области видимости (или ей присваивается другое значение), компилятор вызывает release, что уменьшет счетчик ссылок.
Кокласс уничтожается, когда счетчик ссылок равен 0
Пример:
var
p: pointer;
intf, intf1: IUnknown;
begin
//Здесь: Create + QueryInterface + AddRef
intf := TMyObject.Create; //потомок TInterfacedObject, к примеру
//счетчик = 1
p := pointer(intf);
//счетчик по-прежнему 1, нет приращения, интерфейс берется как указатель
intf1 := intf; //счетчик = 2
intf := nil; // теперь ссылок 1, вызван Release
end; //intf уходит, вызов Release, счетчик = 0 и вызывается TMyObject.Free
Как видно, использование переменных типа интерфейс (внутри - это указатель), приводит к автоматическому отслеживанию ссылок. В случае работы с интерфейсом как с указателем этого не происходит. В случае нескольких интерфейсов ситуация не меняется, счетчик один, и при использовании любого интерфейса он изменяется. Объект уничтожается, когда нет ссылок на все его интерфейсы
masik (2002-04-23 09:52:00) [10]Господа, а если я вообще не использую переменных типа
var
Ptr:TSomeInterface;
то где же ента видимость
И еще, Если я создаю объект ни как описал его "Fantasist"
"(TInterfacedObject.Create as IUnknown) " а просто как объект, то AddRef интерфейса который он описывает не срабатывает. И еще а если интрерфейсов несколько...
Fantasist (2002-04-23 02:18:00) [11]
> When an object is referenced only through interfaces, there
> is no need to destroy it manually; the object is automatically
> destroyed when the last reference to it goes out of scope.
> ...
Хе. Надо было вначале это прочитать, прежде чем аргументировать(это я себе)
приближенный перевод:
... объект автоматически удалиться, когда последняя ссылка на него выйдет из области видимости.
Ни слова об области видимости переменных.
Fantasist (2002-04-23 02:10:00) [12]
> Совершенно верно тянет, потому, что именно об области видимости
> (scope) речь и идет. Вот и Help о том же:
А вы уверены, что scope здесь это область видимости? Не "границы" не "контекст" не "область действия"?
procedure P1;
var
it:IInterface; //то что я слышал - область видимости этой переменной - это область где это символическое имя имеет один и тот же смысл.
begin
...
P2;
...
end;
procedure P2;
begin
... //здесь переменная it не видна. В том смысле, что символическое имя it здесь не опеределенно.
end;
А теперь делаем так:
var
it:^IInterface;
procedure P1;
begin
new(it);
...
end;
procedure P2;
begin
...
dispose(it);
end;
Как вы думаете, что произойдет? Здесь вообще самой переменной типа IInterface невидно нам нигде.
> А то, что ты так долго и подробно описывал - те же яйки,
> только в профиль!
Возможно, но ваша фраза "Delphi удаляет ссылку на интерфейс когда счетчик ссылок на объект становится равным 0" очень, я бы сказал, не однозначна.
> vuk © (23.04.02 00:36)
> Даже больее того. В некоторых случаях счетчик вообще нежелателен,
> например тогда, когда интерфейсы реализуются в компонентах
> и временем жизни экземпляра управляет владелец компонента,
> а не сам экземпляр посредством счетчика ссылок.
Совершенно верно, но если не использовать TInterfacedObject(или его собственную реализацию) как предка, то вообще никаких проблем с тем, что "Делфи удаляет объект раньше чем я" не будет, как было указанно в вопросе.
vuk (2002-04-23 00:36:00) [13]Даже больее того. В некоторых случаях счетчик вообще нежелателен, например тогда, когда интерфейсы реализуются в компонентах и временем жизни экземпляра управляет владелец компонента, а не сам экземпляр посредством счетчика ссылок.
kull (2002-04-22 23:47:00) [14]Более того: если "ручками" сделать AddRef или Release, то потом счетчик кривой будет (конечно если делать это неаккуратно).
kull (2002-04-22 23:43:00) [15]
> Fantasist (22.04.02 22:17)
А то, что ты так долго и подробно описывал - те же яйки, только в профиль!
vuk (2002-04-22 22:43:00) [16]>И что вас всех так прет обзывать это выходом из области
>видимости?
Совершенно верно тянет, потому, что именно об области видимости (scope) речь и идет. Вот и Help о том же:
...
When an object is referenced only through interfaces, there is no need to destroy it manually; the object is automatically destroyed when the last reference to it goes out of scope.
...
Fantasist (2002-04-22 22:17:00) [17]
> А уменьшает счетчик когда переменная содержащая ссылку на
> интерфейс выходит из блока видимости.
И что вас всех так прет обзывать это выходом из области видимости? Область видимости тут совершенно не причем.
В Делфи, все объекты снабженные интерфейсом реализуют три метода: QueryInterface, AddRef и Release. Нас интересуют AddRef и Release. Соответсвенно, должен имется и счетчик - это просто переменная целого типа. AddRef просто увеличивает счетчик на 1, а Release уменьшает его на 1, и если после этого счетчик равен 0, то объект самоуничтожается. Когда вы получаете интерфейс объекта, неважно каким способом, он получается с помощью метода GetInterface класса TObject, который возвращает интерфейс и вызывает AddRef этого интерфейса. И надо учесть, что делфи вызывает Release для переменных типа interface, когда эта переменная уничтожается.
var
it:IUnknown;
begin
it:=(TInterfacedObject.Create as IUnknown); //создается объект, спрашивается его интерфейс(IUnknown) и соответсвенно AddRef - cчетчик равен 1.
...
...
end; //it - уничтожается, но перед этим вызывается Release, счетчик становиться равным 0 - вызывается Destroy.
kull (2002-04-22 18:11:00) [18]1. А где интерфейсные объекты?
2. Result какого типа - может это интерфейс?
3.
> что означает "переменная ... выходит из блока видимости"
пример :
var
i: IMyInterface;
begin
i := TMyInterfaceClass.Create;
.......
end;//вот здесь заканчивается область видимости для i и счетчик уменьшается
masik (2002-04-22 18:06:00) [19]с созданием и удалением разобрался, но попутный вопросик остается в силе
masik (2002-04-22 17:51:00) [20]kull,
что означает "переменная ... выходит из блока видимости"