我已经编写了MFC DLL来加载XML文件或XML字符串并对其进行解析。它用xml元素填充一个映射。我使用的是MSXML2::DOMDocument60,可以解析整个xml。但是如果我在循环中迭代整个过程(200-500次),我可以看到巨大的内存泄漏。我注释了填充映射并迭代了整个xml,然后只有我可以在任务管理器中看到内存泄漏。我检查了所有用于释放的指针,但无法阻止内存泄漏。MSXML6 > LoadFile应用程序接口本身是否存在内存泄漏?你能帮个忙吗?
注意:我在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();发布于 2014-01-06 23:07:09
您需要在for循环的末尾释放pIDOMNode()。
不太确定为什么你的一些变量需要是static的,它们不会占用太多的空间(在我看来它们只是指针)……
发布于 2014-01-07 20:01:06
我可以通过释放BSTR分配的内存来解决这个问题。由于BSTR是一个原始指针,我们需要使用SysFreeString MSDN来释放内存。添加SysFreeString后,我可以看到稳定的内存。我们也可以将BSTR替换为_bstr_t,它的工作方式类似于智能指针。当变量超出作用域时,它会释放内存。谢谢你的帮助!!
https://stackoverflow.com/questions/20952179
复制相似问题