2012-01-10 68 views
0

这段代码会产生巨大的内存泄漏。你能帮我找出它发生的地方吗?Web浏览器(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()是做什么的? – 2012-01-10 23:50:12

回答

3

里面你的循环,对,叫continue当你不叫pElem->Release(),不具有的"input"标记名(这将是最元素)每个retreived元素,这样你就其泄露:

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

虽这么说,你应该重新编写代码,使用ATL的智能指针类(CComPtrCComQIPtrCComBSTR等)来管理内存给你,让你不必手动释放自己的一切了,例如:

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); 
         } 
        } 
       } 
      } 
     } 
    } 
}