2012-01-10 1 views
0

Этот фрагмент кода генерирует огромные утечки памяти. Не могли бы вы помочь мне узнать, где это происходит?Утечки памяти в Webbrowser (COM)

Этот код делает следующее дело:

1) Он получает интерфейс IHTMLDocuments2 2) Запросы на всю коллекцию тегов 3) итерацию по всей коллекции 4) и добавляет некоторые из данных тэгов в список

IDispatch* pDisp; 
pDisp = this->GetHtmlDocument(); 

if (pDisp != NULL) 
{ 
    IHTMLDocument2* pHTMLDocument2; 
    HRESULT hr; 
    hr = pDisp->QueryInterface(IID_IHTMLDocument2,(void**)&pHTMLDocument2); 
    if (hr == S_OK) 
    { 
        // I know that I could use IHTMLDocument3 interface to get collection by ID 
        // but it didn't worked and returned NULL on each call. 
     IHTMLElementCollection* pColl = NULL; 
        // get all tags 
     hr = pHTMLDocument2->get_all(&pColl); 
     if (hr == S_OK && pColl != NULL) 
     { 
      LONG celem; 
      hr = pColl->get_length(&celem); 
      if (hr == S_OK) 
      { 
            //iterate through all tags 
            // if I iterate this block of code in cycle, it 
            // uses memory available upto 2GBs and then 
            // app crashes 
       for (int i=0; i< celem; i++) 
       {      
        VARIANT varIndex; 
        varIndex.vt = VT_UINT; 
        varIndex.lVal = i; 
        VARIANT var2; 
        VariantInit(&var2); 
        IDispatch* pElemDisp = NULL; 
        hr = pColl->item(varIndex, var2, &pElemDisp); 
        if (hr == S_OK && pElemDisp != NULL) 
        { 
         IHTMLElement* pElem; 
         hr = pElemDisp->QueryInterface(IID_IHTMLElement,(void **)&pElem); 
         if (hr == S_OK) 
         {     
                  // check INPUT tags only 
          BSTR tagNameStr = L""; 
          pElem->get_tagName(&tagNameStr); 
          CString tagname(tagNameStr); 
          SysFreeString(tagNameStr); 
          tagname.MakeLower(); 
          if (tagname != "input") 
          { 
           continue; 
          } 
                  //get ID attribute 
          BSTR bstr = L""; 
          pElem->get_id(&bstr); 
          CString idStr(bstr); 
          SysFreeString(bstr); 

          if (RequiredTag(pElem)) 
          {  
           AddTagToList(pElem); 
          } 
                  //release all objects 
          pElem->Release(); 
         } 
         pElemDisp->Release(); 
        } 
       } 
      } 
          // I looked over this code snippet many times and couldn't find what I'm missing here... 
      pColl->Release(); 
     } 
     pHTMLDocument2->Release(); 
    } 
    pDisp->Release();  
} 
+0

Ну ... что делает 'AddTagToList()' do? –

ответ

3

Внутри вашего цикла, для каждого retreived элемента, который не имеет тэг из "input" (который будет большинство элементов), вы не вызывающим pElem->Release() при вызове continue, так что вы их утечек:

if (tagname != "input") 
{ 
    pElem->Release(); // <-- add this 
    continue; 
} 

С учетом сказанного, вы должны переписать свой код, чтобы использовать смарт-классов ATL в указатель (CComPtr, CComQIPtr, CComBSTR и т.д.) для управления памятью для вас, так что вам не придется вручную освободить все сами больше , например:

CComPtr<IDispatch> pDisp; 
pDisp.Attach(this->GetHtmlDocument()); 
if (pDisp.p != NULL)  
{ 
    CComQIPtr<IHTMLDocument2> pHTMLDocument2(pDisp); 
    if (pHTMLDocument2.p != NULL) 
    { 
     CComPtr<IHTMLElementCollection> pColl; 
     pHTMLDocument2->get_all(&pColl); 
     if (pColl.p != NULL) 
     { 
      LONG celem; 
      if (SUCCEEDED(pColl->get_length(&celem))) 
      { 
       for (LONG i = 0; i < celem; ++i) 
       {       
        VARIANT varIndex; 
        varIndex.vt = VT_UINT; 
        varIndex.lVal = i; 
        VARIANT var2; 
        VariantInit(&var2); 
        CComPtr<IDispatch> pElemDisp; 
        pColl->item(varIndex, var2, &pElemDisp); 
        if (pElemDisp.p != NULL) 
        { 
         CComQIPtr<IHTMLElement> pElem(pElemDisp); 
         if (pElem.p != NULL) 
         {      
          CComBSTR tagNameStr; 
          pElem->get_tagName(&tagNameStr); 

          if (lstrcmpiW(tagNameStr.m_str, L"input") != 0) 
           continue; 

          CComBSTR idStr; 
          pElem->get_id(&idStr); 

          if (RequiredTag(pElem))  
           AddTagToList(pElem); 
         } 
        } 
       } 
      } 
     } 
    } 
} 
Смежные вопросы