This snippet of code generate huge memory leaks. Could you help me to find out where it happens?
This code does the following thing:
1) It gets IHTMLDocuments2 interface
2) Requests for all tags collection
3) Iterates over whole collection
4) and adds some of the tags’ data to list
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();
}
Inside your loop, for each retreived element that does not have a tagname of
"input"(which will be most elements), you are not callingpElem->Release()when callingcontinue, so you are leaking them:With that said, you should re-write your code to use ATL’s smart pointer classes (
CComPtr,CComQIPtr,CComBSTR, etc) to manage the memory for you so you do not have to manually release everything yourself anymore, eg: