I have to deal with a legacy application that uses MSXML to write measurement data to a simple XML file. Basicly, this is what's happening:
MSXML2::IXMLDOMDocument2Ptr pXmlDocument;
HRESULT comResult = CXMLUtil::createXMLDocument(pXmlDocument);
// ... check HRESULT ...
MSXML2::IXMLDOMNodePtr pXmlMainNode = pXmlDocument.GetInterfacePtr();
MSXML2::IXMLDOMNodePtr pXmlSubNode = CXMLUtil::AppendNewElement(pXmlDocument, pXmlMainNode, RootTag, "");
// ... create further nodes ...
MSXML2::IXMLDOMNodePtr pXmlTmpNode = CXMLUtil::AppendNewElement(
pXmlDocument,
pXmlDataSetNode,
measDataTag,
measdata,
numberOfDataItems );
// ... append further items ...
After each item, pXmlTmpNode.Release()
is called. At the end, all other nodes as well as pXmlDocument
are Released
.
createXMLDocument
is defined as follows:
HRESULT CXMLUtil::createXMLDocument(MSXML2::IXMLDOMDocument2Ptr &pXmlDocument) {
MSXML2::IXMLDOMDocument2 *xmlDocument = 0;
HRESULT comError = CoCreateInstance(__uuidof(MSXML2::DOMDocument),NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&xmlDocument));
if (comError) return comError;
xmlDocument->put_async(VARIANT_FALSE);
xmlDocument->put_validateOnParse(VARIANT_FALSE);
xmlDocument->put_resolveExternals(VARIANT_FALSE);
xmlDocument->put_preserveWhiteSpace(VARIANT_TRUE);
MSXML2::IXMLDOMDocument2Ptr ptr(xmlDocument);
pXmlDocument = ptr;
return comError;
}
For appending new elements (i.e. unsiged char
arrays), this function is applied:
MSXML2::IXMLDOMNodePtr CXMLUtil::AppendNewElement(MSXML2::IXMLDOMDocument2Ptr pXMLDom, MSXML2::IXMLDOMNodePtr pParent, CComBSTR strElementName, unsigned char* pData, long nData) {
MSXML2::IXMLDOMNodePtr pData1 = pXMLDom->createElement(BSTR(strElementName));
pData1->put_dataType(CComBSTR(_T("bin.base64")));
SAFEARRAY* psa = SafeArrayCreateVector( VT_UI1, 0L, nData);
psa->pvData = pData;
VARIANT var;
VariantInit(&var);
var.parray = psa;
var.vt = (VT_ARRAY | VT_UI1 );
pData1->nodeTypedValue = var;
pParent->appendChild(pData1);
SafeArrayDestroy(psa);
return pData1;
}
Regardless of wether #import <msxml4.dll>
or #import <msxml6.dll>
is used, there seems to be a leak of memory. Since measdata
etc. can be huge, that's a pretty big problem. Is there something I can do to make the code work?
Thanks, Matthew
This code leaks
xmlDocument
.ptr(xmlDocument)
does an extraAddRef
, but there is noRelease
for xmlDocument going out of scope. You use smart ptrs everywhere, no reason not to use one here as well, maybe something like this: