Главная страница
    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.46 MB
Время: 0.043 c
6-1102056721
JohnS
2004-12-03 09:52
2005.02.20
Indy(idFtp) , Выделенка , проблемы


9-1099337514
Colt1978
2004-11-01 22:31
2005.02.20
Задание пути объекту.... (GLScene)


4-1103712547
DelphiN!
2004-12-22 13:49
2005.02.20
Получить температуру процессора


14-1106747786
}|{yk
2005-01-26 16:56
2005.02.20
Требуется программист!


3-1106110286
Janb
2005-01-19 07:51
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
Английский Французский Немецкий Итальянский Португальский Русский Испанский