Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.02.20;
Скачать: CL | DM;

Вниз

COM   Найти похожие ветки 

 
vk220 ©   (2004-05-07 17:01) [0]

Проблема такая: есть интерфейс Data.
Есть подчинённые ему интерфейсы Field.
При создании Field функция _AddRef вызывается конструктором Field.
А при уничтожении Field:

Field := nil;

проверяется счётчик ссылок (в модуле System функ. _Release) и т.к. их не 0,
Field просто не удаляется... соответсвенно проц. BeforeDestruction не вызывается.
Я не очень хорошо знаю технологию COM, если кто-нибудь понял изложенное выше, помогите,
пожалуйста.
Также буду благодарен за ссылки, где можно почитать о COM. (в Delphi)


 
clickmaker ©   (2004-05-07 18:47) [1]

http://rsdn.ru/summary/266.xml


 
Бином Ньютоныч   (2004-05-07 20:25) [2]

Не нужно вызывать AddRef в конструкторе. Как я понял, Field возвращается клиенту методами Data, и Data должен жить, пока жив хотя-бы один Field. Тогда следует в том или ином виде использовать аггрегацию. Пожалуй, наиболее наглядно это можно сделать так:

IField = interface;
IData  = interface
 procedure GetField(out Field: IField);
end;

TData = class(..., IData)
 procedure GetField(out Field: IField);
end;

TField = class(..., IField)
 FController: IUnknown;
 constructor Create(Controller: IUnknown);
end;

procedure TData.GetField(out Field: IField);
begin
 Field:=TField.Create(Self);
end;

constructor TField.Create(Controller: IUnknown);
begin
 FController:=Controller;
end;


Это очень простой случай, зато все наглядно. Также внимательно присмотрись к реализации в TComObject методов IUnknown для самого IUnknown и для других интерфейсов, держа в уме, что аггрегироваться объект может не только по IUnknown, но и по любому другому интерфейсу. Главное четко представлять, когда объект должен оперировать собственным счетчиком ссылок, а когда переправлять вызов контроллеру.


 
vk220 ©   (2004-05-08 19:47) [3]

>Не нужно вызывать AddRef в конструкторе

Я убрал из конструктора эту команду. Счётчик ссылок тем не менее увеличивается. Как у Data, так и у Field.
Я вот чего не могу понять: Счётчик ссылок увеличивается/уменьшается автоматически, или мне надо самому вызывать _AddRef и _Release?
Увеличивается он ещё как, а вот убавляться совсем не хочет.


 
Бином Ньютоныч   (2004-05-09 09:01) [4]

>vk220 ©   (08.05.04 19:47) [3]

Как видишь, в моем примере нет ни одного явного вызова методов IUmknown, тем не менее объекты уничтожаются в нужный момент. Интерфейс в Delphi относится к типам с автоматическим управлением временем жизни. Компилятор сам вставляет вызовы AddRef и Release при присвоении/освобождении интерфейсных переменных. Самому делать эти вызовы нужно только в редких, особых случаях, четко представляя себе происходящее.

var
 A: IData;
 B: IField;

 A:=TData.Create;

Здесь будет создан объект TData, получен указатель на его интерфейс IData и, в процессе присвоения его переменной А, будет вызван метод AddRef.

 A.GetField(B);

Здесь тоже самое для объекта TField. Кроме того, указатель на IUnknown TData будет сохранен в поле FController объекта TField, при этом будет автоматически вызван IUnknown.AddRef объекта TData. Теперь счетчик будет содержать 2.

 A:=nil

Будет вызван метод Release объекта TData, но объект не будет уничтожен, т.к. сохраняется ссылка на него в TField.FController.

 B:=nil;

Здесь будет вызван Release объекта TField, при этом его счетчик ссылок обнулится, в результате чего будет автоматически вызван его деструктор. В процессе уничтожения объекта будет автоматически освобождена ссылка, хранящаяся в поле FController с вызовом Release объекта TData. Его счетчик ссылок обнулится и он тоже будет уничтожен.

Если же у тебя при освобождении интерфейсной переменной объект не уничтожается, то это значит, что где-то осталась неосвобожденная ссылка, либо был лишний несбалансированный вызов AddRef. Возможно, ты используешь перекрестные ссылки:
TData хранит IField, а TField хранит IData.

В таких случаях следует одно из полей сделать типа Pointer и при обращении к нему использовать прямое привидение. При этом автоматический подсчет ссылок производиться не будет.



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

Текущий архив: 2005.02.20;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.052 c
4-1104770694
STK
2005-01-03 19:44
2005.02.20
Открыть и закрыть чужую программу.


4-1104948164
suharew
2005-01-05 21:02
2005.02.20
Как переименовать каталог


14-1106211382
DelphiNew
2005-01-20 11:56
2005.02.20
Изгиб гитары жёлтой


6-1100266424
Ирина
2004-11-12 16:33
2005.02.20
ftp-сервер


3-1106207476
Duka
2005-01-20 10:51
2005.02.20
Структура базы cds