Видалення інтерфейсних об'єктів

Видалення інтерфейсних об'єктів

панове, є набір інтерфейсів і класів, які їх реалізують. Природно виникає питання коректного видалення цих класів. Як я розумію Дельфах видаляє їх раніше ніж я. Як це можна відстежити.







А з чого видно, що
> Дельфах видаляє їх раніше ніж я ..
Є конкретний приклад?

Delphi видаляє посилання на інтерфейс коли лічильник посилань на об'єкт стає рівним 0.
А зменшує лічильник коли змінна містить посилання на інтерфейс виходить з блоку видимості.

Та й все залежить, звичайно від коду.
Природно непогано-б приклад або конкретніше про те чого тобі треба.

І ще попутний питаннячко. Я додаю до списку інтерфейсів ще один, в якому описується тільки один метод, і ентот об'єкт взагалі не дається нормально віддалятися. Як я розумію коли немає явної посилання на нього і компонент невидимий дельфи видаляє його без пердупреждения?

kull,
що означає "змінна. виходить з блоку видимості"

зі створенням і видаленням розібрався, але попутний питаннячко залишається в силі

1. А де інтерфейсні об'єкти?
2. Result якого типу - може це інтерфейс?
3.

> Що означає "змінна. Виходить з блоку видимості"

приклад.

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


> А зменшує лічильник коли змінна містить посилання на
> Інтерфейс виходить з блоку видимості.

І що вас всіх так пре обзивати це виходом з області видимості? Область видимості тут абсолютно ні до чого.

У Делфі, всі об'єкти забезпечені інтерфейсом реалізують три методи: 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 - Лічильник дорівнює 1.
.
.
end; // it - знищується, але перед цим викликається Release, лічильник ставати рівним 0 - викликається Destroy.

> І що вас всіх так пре обзивати це виходом з області
> Видимості?
Абсолютно вірно тягне, тому, що саме про область видимості (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 (22.04.02 22:17)

А то, що ти так довго і докладно описував - ті ж яйки, тільки в профіль!

Більш того: якщо "ручками" зробити AddRef або Release, то потім лічильник кривої буде (звичайно якщо робити це неакуратно).

Навіть больее того. У деяких випадках лічильник взагалі небажаний, наприклад тоді, коли інтерфейси реалізуються в компонентах і часом життя примірника управляє власник компонента, а не сам екземпляр за допомогою лічильника посилань.


> Абсолютно вірно тягне, тому, що саме про область видимості
> (Scope) мова і йде. Ось і Help про те ж:

А ви впевнені, що scope тут це область видимості? Чи не "кордону" не "контекст" не "область дії"?

procedure P1;
var
it: IInterface; // то що я чув - область видимості цієї змінної - це область де це символічне ім'я має один і той же зміст.

procedure P2;
begin
. // тут змінна it, хоч я знаю. В тому сенсі, що символічне ім'я it тут не опеределения.
end;

А тепер робимо так:

procedure P2;
begin
.
dispose (it);






end;

Як ви думаєте, що станеться? Тут взагалі самої змінної типу IInterface невидно нам ніде.

> А то, що ти так довго і докладно описував - ті ж яйки,
> Тільки в профіль!

Абсолютно вірно, але якщо не використовувати TInterfacedObject (або його власну реалізацію) як предка, то взагалі ніяких проблем з тим, що "Делфі видаляє об'єкт раніше ніж я" не буде, як було вказано в питанні.


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

Хе. Треба було спочатку це прочитати, перш ніж аргументувати (це я собі)

Ні слова про область видимості змінних.

Господа, а якщо я взагалі не використовую змінних типу
var
# 032; Ptr: TSomeInterface;
то де ж ента видимість
І ще, Якщо я створюю об'єкт ні як описав його "Fantasist"
"(TInterfacedObject.Create as IUnknown)" а просто як об'єкт, то AddRef інтерфейсу який він описує не спрацьовує. І ще а якщо інтрерфейсов кілька.

end; // intf йде, виклик Release, лічильник = 0 і викликається TMyObject.Free

Як видно, використання змінних типу інтерфейс (всередині - це покажчик), призводить до автоматичного відстеження посилань. У разі роботи з інтерфейсом як з покажчиком цього не відбувається. У разі декількох інтерфейсів ситуація не змінюється, лічильник один, і при використанні будь-якого інтерфейсу він змінюється. Об'єкт знищується, коли немає посилань на всі його інтерфейси


> Ні слова про область видимості змінних.

Викликаємо Help набираємо слово scope:
- "І нехай той перший кине в мене камінь хто скаже що це - дівчинка"

Якщо це не облась видимості або дії ідентифікатора (називайте хоч чому сенс не зміниться), то що це тоді?


procedure P1;
var
it: IInterface; // то що я чув - область видимості цієї змінної - це область де це символічне ім'я має один і той же зміст.

procedure P2;
begin
. // тут змінна it, хоч я знаю. В тому сенсі, що символічне ім'я it тут не опеределения.
end;

procedure P1;
var
it: IInterface;

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

to Fantasist:
Ну да, швидше за область дії.

> Ні слова про область видимості змінних.

Автоматичний підрахунок посилань зав'язаний саме на змінні. Компілятор вставляє код фіналізації інтерфейсної змінної якраз тоді, коли потік управління буде виходити з області дії цієї змінної - при виході з процедури, де вона оголошена або куди була передана в якості параметра а також в деструкції класу, в якому така змінна оголошена як член класу .

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

> І ще а якщо інтрерфейсов кілька.
Пи кількість реалізованих інтерфейсів або про що? Якщо про кількість, то воно ніяк не впливає на лічильник посилань. Вплив роблять тільки запити інтерфейсів.

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;

Може, я помиляюся, але Release () начебто викликається при присвоєнні nil цього вказівником (якщо він вказував на об'єкт). Ось тут-то і можна зловити вивантаження компонента


> Як видно, використання змінних типу інтерфейс (всередині
> - це покажчик), призводить до автоматичного відстеження
> Посилань.

Саме з цього, коли я хочу све тримати під своїм контролем, замість інтерфейсів використовую класи. Типу так:


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

Робота не відрізняється від роботи з інтерфейсом. Це може не завжди зручно і не завжди потрібно, однак дозволяє позбутися нав'язливої ​​допомоги Delphi, яка не завжди до речі.

Так, це покажчик, і вже тому я не люблю називати це "засланням", бо це не завжди одне і теж. Знову ж я не погоджуся з таким твердженням: "змінна виходить з області видимості. Компілятор викликає release" так як "область видимості змінної" означає на мій погляд, зовсім не область, де вона зберігає своє значення (те, що Ви, мабуть, маєте на увазі).

Звичайно не змінитися. Просто якщо ти назавешь паравоз параходе, то інші можуть не зрозуміти, чи то ти не бачиш різниці між параходе і Паравоз, то тобі просто заманулося пограти словами.

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

Так чого ти причепився до людини. "Область видимості" і "область дії" це одне і теж (scope по-англійськи як тут вже правильно помітили). І сенс в ці поняття вкладається однаковий. Серед С-шників так взагалі я вживання "область дії" і не чув ніколи. Завжди кажуть "область видимості", а що там прийнято серед Делфістов вам видніше :). Так що даремно ти людині про параходе розповідав :)

Пам'ять: 0.8 MB
Час: 0.036 c







Схожі статті