COM: Могу ли я позвонить CoUninitialize без вызова Release? - PullRequest
4 голосов
/ 16 сентября 2009

У меня есть сомнения. Я инициализирую COM, выполняю ли CoCreateInstance и использую ли некоторые интерфейсы. Можно ли вызвать CoUninitialize без вызова Release? Это вызывает утечку памяти / ресурсов?

Заранее спасибо, -Mani.

Ответы [ 4 ]

3 голосов
/ 16 сентября 2009

Из MSDN:

http://msdn.microsoft.com/en-us/library/ms688715%28VS.85%29.aspx

CoUninitialize должен быть вызван завершение работы приложения, как последний звонок сделано в библиотеке COM после Приложение скрывает свои основные окна и падает через основной цикл сообщений. Если есть открытые разговоры оставшийся, CoUninitialize начинает модальный цикл сообщений и отправляет любые ожидающие сообщения из контейнеров или сервер для этого приложения COM. От рассылка сообщений, CoUninitialize гарантирует, что приложение не выходит раньше получение всех ожидающих сообщений. Сообщения не-COM отбрасываются.

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

2 голосов
/ 28 сентября 2009

Независимо от того, деинициализирована ли вы COM или нет, пропуск вызовов Release освобождает объекты на стороне сервера, возможно, поддерживая весь сервер без причины (если он не работает как служба). Другими словами, у вас будет утечка памяти на стороне сервера, которую можно устранить только путем перезапуска COM-сервера.

Я помню, как задавал похожие вопросы, когда впервые начал использовать COM. Клиент, над которым я работал, использовал много потоков, и я пытался повторно использовать интерфейсы для различных задач, выполняемых каждым потоком. Это сделало управление кешем интерфейсов довольно сложным. В конце концов, не было никаких ярлыков. Если вы не используете MTA, GIT или маршалинг интерфейса, поток, создавший интерфейс, также должен его освободить.

Чтобы вам было проще, попробуйте использовать CComPtr для управления создаваемыми вами интерфейсами. Как и в случае с обычными указателями, использование умного указателя иногда может значительно облегчить вам жизнь.

1 голос
/ 16 сентября 2009

Вы не должны использовать CoUninitialize () вместо вызова IUnknown::Release() для ваших объектов - это абсолютно разные функции.

IUnknown::Release() просто уменьшит счетчик ссылок на объект и, возможно, приведет к его разрушению. Если маршаллинг не используется, этот вызов выполняется напрямую через vtable (управление передается непосредственно в код COM-сервера), а подсистема COM даже ничего не делает для этого.

CoUninitialize () освободит ресурс, связанный с COM, для вызывающего потока, который, я думаю, является объектом, связанным с маршаллингом. Если маршаллинг не используется, объекты останутся невыпущенными, поскольку только ваш код знает о них.

Вот почему вы не должны использовать одно вместо другого.

0 голосов
/ 16 сентября 2009

AFAIK, CoUninitialize "должен" освободить все COM-ресурсы, используемые в текущем потоке. Я бы не стал на это полагаться. Я предпочел бы убедиться, что я выпустил все до вызова неинициализации.

...