Здравствуйте, nnemo, Вы писали:
N>Если счётчик ссылок на объект, возвращаемый методом Release() больше 0, то корректно ли будет после N>одного вызова Release() "бросать" указатель на интерфейс (pBrowser = NULL)?
Ты должен освободить указатель на интерфейс ТОЛЬКО один раз, и то, если ты им реально владеешь, т.е. получил его от QueryInterface или ее производной (например, CoCreateInstance).
Каково реальное значение (long cnt = pBrowser->Release()) не имее значения. Некоторые реализации вообще возвращают всегда 1.
Предположим, я создал объект IWebBrowser2 (CLSID_WebBroser) при помощи CoCreateInstance() и
подключил к нему свой слушатель событий.
После загрузки страницы я хочу корректно удалить объект.
IWebBrowser2* pBrowser = NULL;
// ...
// ...
// Создаем объект, загружаем страницу, переходим по ссылке ...
// ...
// ...
// если я удаляю объект таким образом:
pBrowser->Release();
pBrowser = NULL;
// то я не уверен, правильно ли я освободил ресурсы, т.к. (long cnt = pBrowser->Release()) > 0;
// а если удаляю так:
while ( pBrowser->Release() > 0L );
// то получаю ошибку в ieframe.dll после выхода из функции
Вопрос в следующем.
Если счётчик ссылок на объект, возвращаемый методом Release() больше 0, то корректно ли будет после
одного вызова Release() "бросать" указатель на интерфейс (pBrowser = NULL)?
Здравствуйте, Vi2, Вы писали:
Vi2>Каково реальное значение (long cnt = pBrowser->Release()) не имее значения. Некоторые реализации вообще возвращают всегда 1.
Спасибо за отклик.
Очень хотелось бы знать, почему вызов делается только один раз. Получается, что COM освобождает ресурсы сам?
Нет ли ссылок на эту инфу, касательно IWebBrowser2? Дело в том, что мне неплохо было бы обосновать свой код.
Здравствуйте, nnemo, Вы писали:
N>Очень хотелось бы знать, почему вызов делается только один раз.
Я немного неточно сказал: сколько раз был вызван AddRef на этом указателе интерфейса, столько раз нужно вызвать Release. Как правило, лишних вызовов на одном указателе не делается, поэтому мои слова в этом смысле справедливы.
N>Получается, что COM освобождает ресурсы сам?
Иногда нужно произвести дополнительные действия, например, отписаться от объекта или разорвать взаимные ссылки объектов, но общий механизм подсчёта ссылок это не затрагивает.
N>Нет ли ссылок на эту инфу, касательно IWebBrowser2? Дело в том, что мне неплохо было бы обосновать свой код.
Не имеет значения конкретный интерфейс — любой интерфейс должен вести себя так.
Информация находится в документации на СОМ. Могу дать только названия тем "Managing Object Lifetimes Through Reference Counting", "Implementing Reference Counting" и "Rules for Managing Reference Counts".
Просто вопрос возник из-за того, что после создания объекта IWebBrowser2 и загрузки документа,
Даже если не вызывался AddRef(), счетчик ссылок на объект оказывается больше нуля ( например 9 ).
Я так понимаю, что это получается в том числе и из-за того, что каждый фрейм документа является самостоятельным
объектом IWebBrowser2.
Всвязи с этим возникает вопрос, приведет ли в этом случае единственный вызов Release()
( pBrowser->Release(); pBrowser = NULL; )
к полному и корректному удалению объекта с полным освобождением памяти и закрытием всех хэндлов.
Здравствуйте, nnemo, Вы писали:
N>Просто вопрос возник из-за того, что после создания объекта IWebBrowser2 и загрузки документа, Даже если не вызывался AddRef(), счетчик ссылок на объект оказывается больше нуля ( например 9 ).
N>Я так понимаю, что это получается в том числе и из-за того, что каждый фрейм документа является самостоятельным объектом IWebBrowser2.
Сам объект может передавать свои указатели в разные места (даже внутри своего сервера, не говоря уж о системе), отслеживая внешние ссылки (например, через IExternalConnection). Возможно, это связано с фреймами.
N>Всвязи с этим возникает вопрос, приведет ли в этом случае единственный вызов Release() ( pBrowser->Release(); pBrowser = NULL; ) к полному и корректному удалению объекта с полным освобождением памяти и закрытием всех хэндлов.
Если сам объект не просит вызвать некий метод завершения работы, такой как Quit, Exit etc., то по стандарту СОМ этого достаточно. Что произойдет реально — xz, особенно если WebBrowser будет Микрософтовский: они сами себе хозяева.
Здравствуйте, nnemo, Вы писали:
N>Просто вопрос возник из-за того, что после создания объекта IWebBrowser2 и загрузки документа, даже если не вызывался AddRef(), счетчик ссылок на объект оказывается больше нуля ( например 9 ).
Не обратил внимание на "даже если". Поэтому отдельно.
AddRef() вызывают многие функции НЕЯВНО, например, QueryInterface() — запрос какого-то интерфейса, а через нее и другие функции CoCreateInstance. Т.е. функции, возвращающие указатель на интерфейс. Им по стандарту СОМ предписано возвращать указатель с увеличенной ссылкой, т.е. был сделан вызов AddRef(). И клиент должен освободить такой указатель вызовом Release().
Vi2>Сам объект может передавать свои указатели в разные места (даже внутри своего сервера, не говоря уж о системе), отслеживая внешние ссылки (например, через IExternalConnection). Возможно, это связано с фреймами.
Vi2>Если сам объект не просит вызвать некий метод завершения работы, такой как Quit, Exit etc., то по стандарту СОМ этого достаточно. Что произойдет реально — xz, особенно если WebBrowser будет Микрософтовский: они сами себе хозяева.
Большое спасибо насчет IExternalConnection.
Я писал, что AddRef() не вызывался, имея ввиду, например такой вариант:
А не проще использовать смарт-поинтеры. Они сами уничтожаются при выходе из поля видимости.
Например:
BOOL PrintPageFromWebBrowser()
{
CComPtr<IWebBrowser2> pWebBrowser; // Работает как обычный указатель на интерфейс
//...
// Создание IWebBrowser2, выполнение каких-то действий (например - печать )
} // В этом месте CComPtr сам вызовет Release для pWebBrowser
Это намного проще и безопаснее, чем работать с простыми интерфейсами.