[英]C++ xml (should I use msxml6?, I installed msxml6 but not see where it is)
[英]Memory Leaks in MSXML6 XML Parsing
我已經編寫了MFC DLL,該DLL可以加載XML文件或XML字符串並進行解析。 它使用xml元素填充一張地圖。 我正在使用MSXML2 :: DOMDocument60並且可以解析整個xml。 但是,如果我在循環中迭代整個過程(200-500次),我可能會看到巨大的內存泄漏。 我評論了填充映射並僅迭代整個xml,然后只有我可以在任務管理器中看到內存泄漏。 我檢查了所有用於釋放的指針,但無法停止此內存泄漏。 MSXML6> LoadFile API本身是否存在內存泄漏? 您能幫上忙嗎?
注意:我已經在Init方法中初始化了COM,而在Dispose方法中未初始化了它。 此代碼。 下面的代碼未提及這些方法。
碼:
C ++ DLL:
bool CXMLSerializer::LoadFile(const char* sXmlData)
{
bool bResult = false;
static SAFEARRAY* psa = NULL;
static MSXML2::IXMLDOMDocumentPtr xmlDocPtr;
//Create an instance of the DOMDocument object:
xmlDocPtr.CreateInstance(__uuidof(MSXML2::DOMDocument60));
try
{
VARIANT_BOOL varResult((bool)FALSE);
if(sXmlData == NULL)
{
_tprintf(_T("XML Data received is Null, Loading XML document from XMLFile\n"));
if(FileExists(m_sXmlFileName))
{
_tprintf(_T("Loading XML: %s\n"), m_sXmlFileName);
//Load a document:
_variant_t varXml(m_sXmlFileName); //XML file to load
varResult = xmlDocPtr->load(varXml);
}
else
{
_tprintf(_T("Failed to open XML file %s\n"), m_sXmlFileName);
}
}
else
{
_tprintf(_T("XML string received, Loading data...\n"));
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = strlen(sXmlData);
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
if(psa != NULL)
{
memcpy(psa->pvData, sXmlData, strlen(sXmlData));
VARIANT v;
VariantInit(&v);
V_VT(&v) = VT_ARRAY | VT_UI1;
V_ARRAY(&v) = psa;
varResult = xmlDocPtr->load(v);
VariantClear(&v);
}
else
{
_tprintf(_T("Error: SafeArrayCreate failed\n"));
}
}
if(varResult == VARIANT_TRUE)
{
_tprintf(_T("XML document loaded successfully\n"));
if (DeserializeRules(xmlDocPtr))
{
_tprintf(_T("XML Deserialized successfully\n"));
bResult = true;
}
else
{
_tprintf(_T("XML Deserialization failed\n"));
}
}
else
{
_tprintf(_T("XML document load failed\n"));
}
}
catch(...)
{
_tprintf(_T("ERROR: Exception occured in LoadFile()\n"));
}
//GetXML
m_sXmlData = SerializeRules(xmlDocPtr);
if(psa)
{
SafeArrayDestroy(psa);
psa = NULL;
}
if(xmlDocPtr)
{
xmlDocPtr.Release();
}
::CoFreeUnusedLibraries();
return bResult;
}
bool CXMLSerializer::DeserializeRules(MSXML2::IXMLDOMDocumentPtr xmlDocPtr)
{
bool bParseResult = false;
static MSXML2::IXMLDOMNodeListPtr NodeListPtr; //indexed access. and iteration through the collection of nodes
static MSXML2::IXMLDOMNode *pIDOMNode = NULL; //pointer to element's node
static MSXML2::IXMLDOMNodeList *pChildList=NULL; //node list containing the child nodes
try
{
//clear data structures
m_pRules->m_mapTitleParserApp.clear();
//Variable with the name of node to find:
BSTR strFindText = L"*"; //" " means to output every node
//Variables to store item's name, parent, text and node type:
BSTR bstrItemText, bstrItemNode, bstrNodeType;
int i = 0; //loop-index variable
bool bResult = false;
CString sApplicationName = L"";
HRESULT hr;
//Collect all or selected nodes by tag name:
NodeListPtr = xmlDocPtr->getElementsByTagName(strFindText);
//root node:
xmlDocPtr->documentElement->get_nodeName(&bstrItemText);
for(i = 0; i < (NodeListPtr->length); i++)
{
if(pIDOMNode) pIDOMNode->Release();
NodeListPtr->get_item(i, &pIDOMNode);
if(pIDOMNode)
{
pIDOMNode->get_nodeTypeString(&bstrNodeType);
//process only elements (nodes of "element" type):
BSTR temp = L"element";
int ft;
CString cs;
//........Commented assigning elements to map.......//
//.......Even I could see Leaks at TaskManager....//
}
}
if(NodeListPtr)
NodeListPtr.Release();
if(pChildList)
pChildList->Release();
bParseResult = true;
m_bIsXMLParsed = true;
_tprintf(_T("Deserialize - Size of mapTitleParserApp: %d\n"), m_pRules->m_mapTitleParserApp.size());
}
catch(...)
{
_tprintf(_T("ERROR: Exception occured in Deserialize()\n"));
}
return bParseResult;
}
CString CXMLSerializer::SerializeRules()
{
CString sXmlData = L"";
sXmlData = (LPCTSTR) m_xmlDocPtr->Getxml();
return sXmlData;
}
C#測試應用程序:
strDataDir = @"C:\temp";
string sXMLData = null;
NativeDLLHelper.Init(strUserDataDir, 15);
for (i = 0; i < 500; i++)
{
NativeDLLHelper.LoadFile(sXMLData);
Console.WriteLine("i: " + i);
}
NativeDLLHelper.Dispose();
Console.ReadLine();
您需要在for循環結束時釋放pIDOMNode()
。
不太確定為什么有些變量需要為static
變量,它們占用的空間不多(據我所知,它們只是指針)...
我可以通過釋放BSTR分配的內存來解決此問題。 由於BSTR是原始指針,因此我們需要使用SysFreeString MSDN釋放內存。 添加SysFreeString之后,我可以看到穩定的內存。 同樣,我們可以將BSTR替換為_bstr_t,其工作方式類似於智能指針。 當變量超出范圍時,它將釋放內存。 感謝你的幫助!!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.