Как правильно освободить ресурсы после использования MsHTML?

Обсуждение вопросов, касающихся указанной технологии.
Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Как правильно освободить ресурсы после использования MsHTML?

Сообщение Admiralisimys » 20.02.2012 (Пн) 23:30

Здравствуйте.

Иллюстрирующий проблему код
Код: Выделить всё
#include <tchar.h>
#include <MsHTML.h>
//see http://support.microsoft.com/kb/231931
#pragma warning(disable : 4049)
#pragma warning(disable : 4146)
#pragma warning(disable : 4192)
#pragma warning(disable : 4278)
#import <mshtml.tlb>
#pragma warning(default: 4049)
#pragma warning(default: 4146)
#pragma warning(default: 4192)
#pragma warning(default: 4278)

int _tmain(int argc, TCHAR *argv[])
{
   HRESULT hr = CoInitialize(NULL);
   if(FAILED(hr))
      return -1;

   MSHTML::IHTMLDocument2Ptr pDoc = NULL;
   MSHTML::IHTMLDocument3Ptr pDoc3 = NULL;

   hr = CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER,
         IID_IHTMLDocument2, (void**)&pDoc);

   if(FAILED(hr))
      return -1;
   //Access violation reading location
   //if(pDoc)
   //   pDoc->Release();
   //pDoc = NULL;

   CoUninitialize();

   return 0;
   //Access violation reading location
   //and go to COM interface pointers header (comip.h)
}

В таком виде, программа заканчивает работу с исключением после return 0.
При запуске из-под Visual C++ (тестировалось в Express Edition 2008/2010) сваливается на освобождении COM интерфейса в файле comip.h
Если используемый интерфейс освобождать самостоятельно, то во время выполнения в окне OutPut будет поступать информация о множественных Access violation reading location.

Если поменять местами CoUninitialize() и освобождение (pDoc->Release()), как приводил пример Андре Ламот по другому COM интерфейсу, то исключение на этом освобождении.

Как быть?

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Как правильно освободить ресурсы после использования MsH

Сообщение Хакер » 21.02.2012 (Вт) 7:08

Всё элементарно.

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

В то же время вызов Release закомментирован:

Код: Выделить всё
   //Access violation reading location
   //if(pDoc)
   //   pDoc->Release();
   //pDoc = NULL;


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

А падало здесь оно по той причине, что ты испоьзуешь так называемый умные указатели. Вызов AddRef и Release происходит автоматически там, где это нужно. Таким образом, происходит два вызова Release — первый вручную (тобою), а второй автоматически (при pDoc = NULL). Из-за двух вызовов Release и падает.

pDoc = NULL; надо оставить, а if(pDoc) pDoc->Release(); — убрать. Оператор присваивания перегружен, при присваивании переменной значения NULL проверка значения pDoc и вызов Release при ненулевом значении происходят автоматически.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: Как правильно освободить ресурсы после использования MsH

Сообщение Admiralisimys » 22.02.2012 (Ср) 10:28

Ах, вот что оно Хакер

До этого первая ассоциация на термин умный указатель - auto_ptr из stl, а совсем уж не давних времён ещё и shared_ptr из boost. Теперь буду знать, что и в COM есть такой инструмент.
В примерах по DirectX, а именно через него имел дело с COM, по каким-то причинам (не уж-то из соображений быстродействия) такой тип данных не используется, по этому там всегда нужно вызывать Release() самостоятельно, а то, что AddRef вызывается негласно, был в курсе.

Спасибо, теперь без ошибок, программа работает гладко.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Как правильно освободить ресурсы после использования MsH

Сообщение Хакер » 22.02.2012 (Ср) 10:32

Admiralisimys писал(а):Теперь буду знать, что и в COM есть такой инструмент.

В COM таких указателей нету. В С++ такое дело есть, а COM глубоко наплевать на такой частный случай, как С++.

Вообще, в чём смысл для таких целей использовать С/С++, когда идеальным инструментом для этого будет VB6?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: Как правильно освободить ресурсы после использования MsH

Сообщение Admiralisimys » 22.02.2012 (Ср) 10:45

Хакер я использовал MsHTML в VB.NET, появилась необходимость опробовать ещё и в Native приложении. В первую очередь выбор пал на Visual C++.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Как правильно освободить ресурсы после использования MsH

Сообщение Хакер » 22.02.2012 (Ср) 10:53

Ну так используй VB6. COM — это его стихия.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в OLE / COM / ActiveX

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

    TopList