Главная страница
    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.47 MB
Время: 0.046 c
1-1107514581
Brenagwynn
2005-02-04 13:56
2005.02.20
Распарсить большой текстовый файл


1-1107775149
cad2206
2005-02-07 14:19
2005.02.20
Изображение из TChart a в TImage. КАК!?


14-1106800554
Девушка
2005-01-27 07:35
2005.02.20
Сотовый - подслушивающее устройство?


1-1107715358
Владимир Кладов
2005-02-06 21:42
2005.02.20
помогите "чайнику"


3-1106114416
AleKo
2005-01-19 09:00
2005.02.20
Редактирование перед сохранением.





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