Как умирают повисшие объекты?
От: Аноним  
Дата: 17.02.05 14:56
Оценка:
Глупый вопрос...
А что происходит, если при использовании COM объекта
сделать на один Release меньше, чем AddRef?
Понятно, что такие объкты висят до завершения работы программы.
А вот кто и как их потом прибивает и возможны
ли из-за этого проблемы типа access violation и прочих серьезных.

Вопрос возник из-за GUI, написанного на Borland Builder C++.
Этот самый GUI использует COM объект с методом, в который
передается другой COM объект ([in] параметр)
Так вот бормановские врапперы похоже вызывают на один Release
меньше, чем положено и в итоге имею кучу leak'ов.

P.S. Это кстати пример в тему почему BCB не стоит использовать
даже для написания простеньких COM клиентов.
Мне похоже даже с врапперами продется насильно вызывать Release.
Нафига блин нужны такие врапперы
Re: Как умирают повисшие объекты?
От: Sergey Россия  
Дата: 17.02.05 15:42
Оценка:
Hello, !
You wrote on Thu, 17 Feb 2005 14:56:03 GMT:

> Глупый вопрос...

> А что происходит, если при использовании COM объекта
> сделать на один Release меньше, чем AddRef?
> Понятно, что такие объкты висят до завершения работы программы.

> А вот кто и как их потом прибивает


ExitProcess прибивает. Впрочем, он не в курсе, что это именно COM-объекты.
Он все на свете прибивает.

> и возможны ли из-за этого проблемы типа access violation и прочих

> серьезных.

Запросто.

With best regards, Sergey.
Posted via RSDN NNTP Server 1.9
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re: Как умирают повисшие объекты?
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 17.02.05 15:48
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Этот самый GUI использует COM объект с методом, в который

А>передается другой COM объект ([in] параметр)
А>Так вот бормановские врапперы похоже вызывают на один Release
А>меньше, чем положено и в итоге имею кучу leak'ов.

да, тоже наступали на это дело, если передавать параметром указатель на интерфейс, дебилдер в реализации метода лепит вокруг него свою обертку и при заключении переданного указателя на интерфейс в эту обертку делает AddRef(), но в деструкторе обертки никаких Release() нету. Пришлось вставлять в каждый такой дебилдерный метод принудительный Release() для соблюдения баланса
Re: Как умирают повисшие объекты?
От: Tom Россия http://www.RSDN.ru
Дата: 17.02.05 15:49
Оценка:
А у тебя случаем не кольцевая ссылка получется?
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re[2]: Как умирают повисшие объекты?
От: Аноним  
Дата: 17.02.05 15:53
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>А у тебя случаем не кольцевая ссылка получется?


Нет. В этом смысле все чисто.
Прогнал BoundsChecker и во всех таких ситуациях показывается
стабильный leak с refCounter равный 1.
Все точно блин, как в аптеке, только не правильно
Re[2]: Как умирают повисшие объекты?
От: Аноним  
Дата: 17.02.05 15:59
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, <Аноним>, Вы писали:


А>>Этот самый GUI использует COM объект с методом, в который

А>>передается другой COM объект ([in] параметр)
А>>Так вот бормановские врапперы похоже вызывают на один Release
А>>меньше, чем положено и в итоге имею кучу leak'ов.

OE>да, тоже наступали на это дело, если передавать параметром указатель на интерфейс, дебилдер в реализации метода лепит вокруг него свою обертку и при заключении переданного указателя на интерфейс в эту обертку делает AddRef(), но в деструкторе обертки никаких Release() нету. Пришлось вставлять в каждый такой дебилдерный метод принудительный Release() для соблюдения баланса


Блин, а у меня таких мест уже довольно много.
А вот BCB6 похоже генерит нормальные врапперы и как теперь писать
"портабельный" в мире дебилдера код?
Мало того, что принудительный Release() нужен,
так еще и в таком вот стиле.
#if __BORLANDC__ < 0x0560    // BCB5
  pMyComObj->Release();
#endif

Замечательно
Re[2]: Как умирают повисшие объекты?
От: Аноним  
Дата: 17.02.05 16:02
Оценка:
Здравствуйте, Sergey, Вы писали:

S>Hello, !

S>You wrote on Thu, 17 Feb 2005 14:56:03 GMT:

>> Глупый вопрос...

>> А что происходит, если при использовании COM объекта
>> сделать на один Release меньше, чем AddRef?
>> Понятно, что такие объкты висят до завершения работы программы.

>> А вот кто и как их потом прибивает


S>ExitProcess прибивает. Впрочем, он не в курсе, что это именно COM-объекты.

S>Он все на свете прибивает.

>> и возможны ли из-за этого проблемы типа access violation и прочих

>> серьезных.

S>Запросто.


Вот именно это у меня время от времени и происходит.
В самый последний момент, когда уже почти все выгружено,
иногда программа вываливается по access violation.
Может я конечно еще где косячу,
но BoundsChecker кроме ликов COM интерейсов ничего не показывает.
Re: Как умирают повисшие объекты?
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 17.02.05 16:52
Оценка: -1
Здравствуйте, Аноним, Вы писали:

А>Глупый вопрос...

А>А что происходит, если при использовании COM объекта
А>сделать на один Release меньше, чем AddRef?

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

Естественно, что когда завершит работу основной процесс, ресурсы (контролируемые Windows) освободятся. (Это я на всякий случай написал)

Основной нюанс с который нужно учитывать при работе с VCL и COM-обектами — VCL выполняет деинициализацию COM до разрушения форм. Это я про то, что делается после выхода из WinMain.

Возможно это связано с порядком деинициализации внутренностей этой библиотеки. В результате получаешь смарт-указатель который указывает на адресное пространство выгруженной DLL. Но это проблема успешно решается.

>P.S. Это кстати пример в тему почему BCB не стоит использовать

А>даже для написания простеньких COM клиентов.

Не, я думаю что тем кто задает такие вопросы лучше вообще c COM не связываться

Борманоские врапперы... реальные пацаны, понимающие природу и опасность COM-технологии, используют свои, которым доверяют на 100%. Своими же становятся всесторонне проверенные чужие. И у них все работает. Так что не будем тут пальцы гнуть.

Что не нравится мой комментарий? Ну дык лучше было держать свое мнение при себе
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[2]: Как умирают повисшие объекты?
От: Аноним  
Дата: 17.02.05 20:12
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, Аноним, Вы писали:


А>>Глупый вопрос...

А>>А что происходит, если при использовании COM объекта
А>>сделать на один Release меньше, чем AddRef?

КД>Объект будет утерян. И память которую он занимает уже никому не достанется. Кроме того — объект может заблокировать некие внешние ресурсы (файлы, сетевые подлючения и т.д.). Так же, в случае DLL-сервера, DLL (создавшую этот объект) не получится выгрузить из процесса — COM будет считать, что в ней есть активные объекты.


КД>Естественно, что когда завершит работу основной процесс, ресурсы (контролируемые Windows) освободятся. (Это я на всякий случай написал)


КД>Основной нюанс с который нужно учитывать при работе с VCL и COM-обектами — VCL выполняет деинициализацию COM до разрушения форм. Это я про то, что делается после выхода из WinMain.


И что это означает? Следует ли из этого,
что в деструкторах форм использовать COM объекты не рекомендуется?


КД>Возможно это связано с порядком деинициализации внутренностей этой библиотеки. В результате получаешь смарт-указатель который указывает на адресное пространство выгруженной DLL. Но это проблема успешно решается.


Как?

>>P.S. Это кстати пример в тему почему BCB не стоит использовать

А>>даже для написания простеньких COM клиентов.

КД>Не, я думаю что тем кто задает такие вопросы лучше вообще c COM не связываться


Ну в таком случае тех, кто реализовал такие врапперы надо просто не допускать к компьютерам.

КД>Борманоские врапперы... реальные пацаны, понимающие природу и опасность COM-технологии, используют свои, которым доверяют на 100%. Своими же становятся всесторонне проверенные чужие. И у них все работает. Так что не будем тут пальцы гнуть.


tlbimp видимо тоже использовать крайне не рекомендуется

КД>Что не нравится мой комментарий? Ну дык лучше было держать свое мнение при себе


Да, мне твой комментарий не нравится.
Но если я высказал свое фи по поводу продукта,
который уже мертв именно из-за своих многочисленных проблем.
То ты наехал лично на меня.
Наверное ты из Борланда и писал эти самые врапперы

Я, кстати, совсем не спец в BCB.
Я отвечаю за COM сервер, который юзается борландовым клиентом.
С клиентами на васике и многих других языках проблем нету,
а в вот с борманом (причем похоже только 5-м) нужен особый подход.
Это достаточный повод для недовольства.
Re[3]: Как умирают повисшие объекты?
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 17.02.05 21:36
Оценка:
Здравствуйте, Аноним, Вы писали:

КД>>Основной нюанс с который нужно учитывать при работе с VCL и COM-обектами — VCL выполняет деинициализацию COM до разрушения форм. Это я про то, что делается после выхода из WinMain.


А>И что это означает? Следует ли из этого,

А>что в деструкторах форм использовать COM объекты не рекомендуется?

Это означает то, что при разрушении объекта формы будут вызваны деструкторы смарт-указателей, которые вызовут Release для объектов из выгруженных DLL. Занавес.

КД>>Возможно это связано с порядком деинициализации внутренностей этой библиотеки. В результате получаешь смарт-указатель который указывает на адресное пространство выгруженной DLL. Но это проблема успешно решается.


А>Как?

CoInitialize/CoUnitialize в формах, которые живут до конца существования приложения.

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

Но, между нами девочками, я на это забивал и просто вставлял CoInitialize в начало WinMain

А>Ну в таком случае тех, кто реализовал такие врапперы надо просто не допускать к компьютерам.

Ну дык студенты, блин, писали.

А>tlbimp видимо тоже использовать крайне не рекомендуется

Никогда не пользовался.

А>Я отвечаю за COM сервер, который юзается борландовым клиентом.

А>С клиентами на васике и многих других языках проблем нету,

Ну дык и написал бы для него нормальный враппер. Руками на С++. А не мышью через меню.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Как умирают повисшие объекты?
От: Аноним  
Дата: 17.02.05 22:34
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, Аноним, Вы писали:


КД>>>Основной нюанс с который нужно учитывать при работе с VCL и COM-обектами — VCL выполняет деинициализацию COM до разрушения форм. Это я про то, что делается после выхода из WinMain.


А>>И что это означает? Следует ли из этого,

А>>что в деструкторах форм использовать COM объекты не рекомендуется?

КД>Это означает то, что при разрушении объекта формы будут вызваны деструкторы смарт-указателей, которые вызовут Release для объектов из выгруженных DLL. Занавес.


Забавно. Чем дальше в лес, тем толще партизаны.


КД>>>Возможно это связано с порядком деинициализации внутренностей этой библиотеки. В результате получаешь смарт-указатель который указывает на адресное пространство выгруженной DLL. Но это проблема успешно решается.


А>>Как?

КД>CoInitialize/CoUnitialize в формах, которые живут до конца существования приложения.

КД>Причем CoUnitialize должен вызываться после разрушения последнего смарт-указателя. Сия задача решается обертывание (в мокрую простыню ) этих двух вызовов в класс (конструктор-деструктор) и помещение этого объекта в первым членом в список членов класса.


КД>Но, между нами девочками, я на это забивал и просто вставлял CoInitialize в начало WinMain


Наверное я тоже так же сделаю (CoInitialize в начало WinMain).
Хоть и не кошерно, но зато только в одном месте.

В общем спасибо за идеи!
Re[2]: Как умирают повисшие объекты?
От: Sergei  
Дата: 15.01.06 15:29
Оценка: 22 (1)
#Имя: FAQ.com.cbuilder.pinterface
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, <Аноним>, Вы писали:


А>>Этот самый GUI использует COM объект с методом, в который

А>>передается другой COM объект ([in] параметр)
А>>Так вот бормановские врапперы похоже вызывают на один Release
А>>меньше, чем положено и в итоге имею кучу leak'ов.

OE>да, тоже наступали на это дело, если передавать параметром указатель на интерфейс, дебилдер в реализации метода лепит вокруг него свою обертку и при заключении переданного указателя на интерфейс в эту обертку делает AddRef(), но в деструкторе обертки никаких Release() нету. Пришлось вставлять в каждый такой дебилдерный метод принудительный Release() для соблюдения баланса


Позволю не согласится.
В BCB5
Обертка, которая используется для передачи интерфейса генерится следующим образом
typedef TComInterface< <имя интерфейса>, <IID> > <имя интерфейса>Ptr
где

template <class T,
          const IID *piid = &GUID_NULL> /* NOTE: The IID parameter is for backward-compatibility*/
                                        /*       New code should rely on __uuidof(intf) support */
class TComInterface
{
public:
  TComInterface() : intf(0)
  {}

  // NOTE: The default behaviour of the constructor is to not AddRef the interface
  //       pointer parameter. This is appropriate if the interface was obtained
  //       has already been addRef'ed - as when retrieving a Font property.
  //
  TComInterface(T* p, bool addRef = false)
  {
    if (((intf = p) != 0) && addRef)
      intf->AddRef();
  } 
.....
  TComInterface(const TComInterface<T, piid>& src)
   {
    if ((intf = src.intf) != 0)
      intf->AddRef();
  }
// NOTE: This assignment operator does *NOT* addRef the interface pointer being
  //       assigned to this object.
  //
  TComInterface<T, piid>& operator=(T* p)
  {
    Bind(p);
    return *this;
  }
  TComInterface<T, piid>& operator=(const TComInterface<T, piid>& src)
  {
    if (src.intf != 0)
      src.intf->AddRef();
    Reset(src.intf);
    return *this;
  }
.....

  void Reset(T* p = 0)
  {
    if (intf)
      intf->Release();
    intf=p;
  }

~TComInterface()
  {
    Reset();
  }


Видно, что Release() вызывается всегда.

Так что скорее должен вызываться лишний Release().
Re[3]: Как умирают повисшие объекты?
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 16.01.06 05:40
Оценка:
Здравствуйте, Sergei, Вы писали:

S>Так что скорее должен вызываться лишний Release().


да, лажанулся за давностью лет Сейчас посмотрел исходники — там действительно ручками вызывается AddRef(), именно потому, что

The default behaviour of the constructor is to not AddRef the interface pointer parameter.

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Как умирают повисшие объекты?
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 18.01.06 15:24
Оценка:
Здравствуйте, Sergei, Вы писали:

S>Позволю не согласится.

S>В BCB5

S>void Reset(T* p = 0)
S>{
S> if(intf)
S>  intf->Release();
S> intf=p;
S>}

Мурашки по коже от такой реализации освобождения интерфейса.

Я же говорю, студенты, блин, писали.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.