Мне приходится иметь дело с унаследованным приложением, которое использует MSXML для записи данных измерений в простой XML-файл. По сути, это то, что происходит:
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 ...
После каждого предмета pXmlTmpNode.Release()
называется. В конце концов, все остальные узлы, а также pXmlDocument
являются Released
,
createXMLDocument
определяется следующим образом:
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;
}
Для добавления новых элементов (т.е. unsiged char
массивов), эта функция применяется:
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;
}
Независимо от погоды #import <msxml4.dll>
или же #import <msxml6.dll>
используется, кажется, есть утечка памяти. поскольку measdata
и т.д. может быть огромным, это довольно большая проблема. Что я могу сделать, чтобы заставить код работать?
Спасибо Мэтью
MSXML2::IXMLDOMDocument2 *xmlDocument = 0;
HRESULT comError = CoCreateInstance(__uuidof(MSXML2::DOMDocument),
NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&xmlDocument));
...
MSXML2::IXMLDOMDocument2Ptr ptr(xmlDocument);
pXmlDocument = ptr;
Этот код утечки xmlDocument
, ptr(xmlDocument)
делает лишнее AddRef
, но нет Release
для xmlDocument выходит за рамки. Вы используете smart ptrs везде, нет причин не использовать его здесь, может быть что-то вроде этого:
MSXML2::IXMLDOMDocument2Ptr xmlDocument;
HRESULT comError = CoCreateInstance(__uuidof(MSXML2::DOMDocument),
NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&xmlDocument));
...
pXmlDocument = xmlDocument;
Других решений пока нет …