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

Вниз

Удаление интерфейсных объектов   Найти похожие ветки 

 
masik   (2002-04-22 17:21) [0]

господа, есть набор интерфейсов и классов, которые их реализует. Естественно возникает вопрос корректного удаления этих классов. Как я понимаю Дельфя удаляет их раньше чем я. Как это можно отследить.


 
Cobalt   (2002-04-22 17:30) [1]

А из чего видно, что
> Дельфя удаляет их раньше чем я.?
Есть конкретный пример?


 
kull   (2002-04-22 17:31) [2]

Delphi удаляет ссылку на интерфейс когда счетчик ссылок на объект становится равным 0.
А уменьшает счетчик когда переменная содержащая ссылку на интерфейс выходит из блока видимости.


 
kull   (2002-04-22 17:32) [3]

Да и все зависит, конечно от кода.
Естественно неплохо-бы пример или конкретней о том чего тебе надо.


 
masik   (2002-04-22 17:48) [4]

Код откровенно огроменный и многомодульный,но попробую объяснить.
объекты - VCL компоненты, при создании объекта его ссылка заносится в List
Result:=TControlClass(FindClass(ControlClass)).Create(Self);
FControls.Add(Result);
при очистке списка и удалении компонентов все нормально
for i:=FControls.Count-1 downto 0 do begin
TObject(FControls.Items[i]).Free;
FControls.Delete(i);
end;
а при завершении проекта EXCEPTION.

И еще попутный вопросик. Я добавляю к списку интерфейсов еще один, в котором описывается только один метод, и ентот объект вообще не дается нормально удаляться. Как я понимаю когда нет явной ссылки на него и компонент невидим дельфи удаляет его без пердупреждения?


 
masik   (2002-04-22 17:51) [5]

kull,
что означает "переменная ... выходит из блока видимости"


 
masik   (2002-04-22 18:06) [6]

с созданием и удалением разобрался, но попутный вопросик остается в силе


 
kull   (2002-04-22 18:11) [7]

1. А где интерфейсные объекты?
2. Result какого типа - может это интерфейс?
3.

> что означает "переменная ... выходит из блока видимости"

пример :

var
i: IMyInterface;
begin
i := TMyInterfaceClass.Create;
.......
end;//вот здесь заканчивается область видимости для i и счетчик уменьшается


 
Fantasist   (2002-04-22 22:17) [8]


> А уменьшает счетчик когда переменная содержащая ссылку на
> интерфейс выходит из блока видимости.


И что вас всех так прет обзывать это выходом из области видимости? Область видимости тут совершенно не причем.

В Делфи, все объекты снабженные интерфейсом реализуют три метода: 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.


 
vuk   (2002-04-22 22:43) [9]

>И что вас всех так прет обзывать это выходом из области
>видимости?
Совершенно верно тянет, потому, что именно об области видимости (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.
...


 
kull   (2002-04-22 23:43) [10]


> Fantasist (22.04.02 22:17)

А то, что ты так долго и подробно описывал - те же яйки, только в профиль!


 
kull   (2002-04-22 23:47) [11]

Более того: если "ручками" сделать AddRef или Release, то потом счетчик кривой будет (конечно если делать это неаккуратно).


 
vuk   (2002-04-23 00:36) [12]

Даже больее того. В некоторых случаях счетчик вообще нежелателен, например тогда, когда интерфейсы реализуются в компонентах и временем жизни экземпляра управляет владелец компонента, а не сам экземпляр посредством счетчика ссылок.


 
Fantasist   (2002-04-23 02:10) [13]


> Совершенно верно тянет, потому, что именно об области видимости
> (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(или его собственную реализацию) как предка, то вообще никаких проблем с тем, что "Делфи удаляет объект раньше чем я" не будет, как было указанно в вопросе.


 
Fantasist   (2002-04-23 02:18) [14]


> 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.
> ...


Хе. Надо было вначале это прочитать, прежде чем аргументировать(это я себе)

приближенный перевод:

... объект автоматически удалиться, когда последняя ссылка на него выйдет из области видимости.


Ни слова об области видимости переменных.


 
masik   (2002-04-23 09:52) [15]

Господа, а если я вообще не использую переменных типа
var
Ptr:TSomeInterface;
то где же ента видимость
И еще, Если я создаю объект ни как описал его "Fantasist"
"(TInterfacedObject.Create as IUnknown) " а просто как объект, то AddRef интерфейса который он описывает не срабатывает. И еще а если интрерфейсов несколько...


 
Romkin   (2002-04-23 10:45) [16]

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

Как видно, использование переменных типа интерфейс (внутри - это указатель), приводит к автоматическому отслеживанию ссылок. В случае работы с интерфейсом как с указателем этого не происходит. В случае нескольких интерфейсов ситуация не меняется, счетчик один, и при использовании любого интерфейса он изменяется. Объект уничтожается, когда нет ссылок на все его интерфейсы


 
kull   (2002-04-23 10:51) [17]


> Ни слова об области видимости переменных.


Вызываем 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;


 
kull   (2002-04-23 10:53) [18]

Ну не область видимости... Назовите как угодно смысл не изменится.


 
vuk   (2002-04-23 10:59) [19]

to Fantasist:
Ну да, скорее область действия.

>объект автоматически удалиться, когда последняя ссылка на него
>выйдет из области видимости.

>Ни слова об области видимости переменных.

Автоматический подсчет ссылок завязан именно на переменные. Компилятор вставляет код финализации интерфейсной переменной как раз тогда, когда поток управления будет выходить из области действия этой переменной - при выходе из процедуры, где она объявлена или куда была передана в качестве параметра а также в деструкторе класса, в котором такая переменная объявлена как член класса.

>Господа, а если я вообще не использую переменных
Если Вы вообще не запрашиваете интерфейсы у объекта, то подсчет ссылок не работает и никак не влияет на функционирование. Если же Вы в одном месте используете экземпляр обычным образом, а в другом запрашиваете у него интерфейсы, то Вам нужно либо переопределить механизм подсчета ссылок, либо в первом случае завести дополнительную интерфейсную ссылку - как раз для того, чтобы контролировать время жизни экземпляра.

>И еще а если интрерфейсов несколько...
Во про количество реализуемых интерфейсов или о чем? Если о количестве, то оно никак не влияет на счетчик ссылок. Влияние оказывают только запросы интерфейсов.




 
Бурундук   (2002-04-23 12:31) [20]

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 16:29) [21]

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


 
Krok   (2002-04-23 16:39) [22]

Может, я ошибаюсь, но Release() вроде бы вызывается при присвоении nil этому указателю(если он указывал на объект). Вот тут-то и можно поймать выгрузку компонента


 
Fantasist   (2002-04-24 02:42) [23]


> Как видно, использование переменных типа интерфейс (внутри
> - это указатель), приводит к автоматическому отслеживанию
> ссылок.


Именно по этому, когда я хочу све держать под своим контролем, вместо интерфейсов использую классы. Типа так:


TInterface=class
QueryInterface(ID:TGUID; out Obj); virtual;
AddRef; virtual;
Release; virtual;
end;


Работа не отличается от работы с интерфейсом. Это может не всегда удобно и не всегда нужно, однако позволяет избавиться от навязчивой помощи Delphi, которая не всегда кстати.


> Хотя "ссылка" - все-таки правильнее, переменная типа интерфейс
> - это именно указатель, когда эта переменная выходит из
> области видимости (или ей присваивается другое значение),
> компилятор вызывает release, что уменьшет счетчик ссылок.


Да, это указатель, и уже поэтому я не люблю называть это "ссылкой", ибо это не всегда одно и тоже. Опять же я не соглашусь с этой фразой: "переменная выходит из области видимости ... компилятор вызывает release" так как "область видимости переменной" означает на мой взгляд, совсем не область, где она сохраняет свое значение (то, что Вы, видимо, имеете ввиду).


> Автоматический подсчет ссылок завязан именно на переменные.
>

Безусловно. Я имел ввиду, что там не говорилось о области видимости перемнных типа интерфейс.

> kull © (23.04.02 10:53)
> Ну не область видимости... Назовите как угодно смысл не
> изменится.


Конечно не измениться. Просто если ты назавешь паравоз параходом, то остальные могут не понять, то ли ты не видишь разницы между параходом и паравозом, то ли тебе просто вздумалось поиграть словами.


 
Suntechnic   (2002-04-24 05:49) [24]

Fantasist (24.04.02 02:42)
Конечно не измениться. Просто если ты назавешь паравоз параходом, то остальные могут не понять, то ли ты не видишь разницы между параходом и паравозом, то ли тебе просто вздумалось поиграть словами.

Да чего ты пристал к человеку. "Область видимости" и "область действия" это одно и тоже (scope по-английски как тут уже правильно заметили). И смысл в эти понятия вкладывается одинаковый. Среди С-шников так вообще я употребление "область действия" и не слышал никогда. Всегда говорят "область видимости", а что там принято среди Делфистов вам видней :). Так что зря ты человеку про параходы рассказывал :)



Страницы: 1 вся ветка

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

Наверх




Память: 0.53 MB
Время: 0.004 c
4-17732
a_k_v
2002-01-22 08:36
2002.05.06
OPC + Delphi + SafeArray =???


3-17497
Бульбаш
2002-04-12 17:06
2002.05.06
Проблемы с ODAC 3.6


1-17558
ruslan_as
2002-04-22 10:15
2002.05.06
Ошибка при импорте текстового файла с разделителем


1-17624
Axenow
2002-04-21 12:41
2002.05.06
Помогите расположить текст вертикально.


1-17550
sergey32
2002-04-23 15:58
2002.05.06
При редактировании года в DateTimePicker приложение виснет





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