【问题标题】:Memory leaks in Webbrowser (COM)Webbrowser (COM) 中的内存泄漏
【发布时间】:2012-01-11 08:47:40
【问题描述】:

这段代码会产生巨大的内存泄漏。你能帮我找出它发生在哪里吗?

这段代码做了以下事情:

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

【问题讨论】:

  • 嗯...AddTagToList() 是做什么的?

标签: c++ com memory-leaks browser


【解决方案1】:

在你的循环中,对于每个没有"input" 标记名的检索元素(这将是大多数元素),你在调用continue 时没有调用pElem-&gt;Release(),所以你正在泄漏它们:

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

【讨论】:

    猜你喜欢
    • 2013-12-29
    • 2013-05-12
    • 2012-07-30
    • 1970-01-01
    • 2013-08-02
    • 2011-02-15
    • 2011-06-17
    • 1970-01-01
    • 2011-08-05
    相关资源
    最近更新 更多