XML 파일이나 XML 문자열을로드하고 구문 분석하는 MFC DLL을 작성했습니다. 지도에 xml 요소를 채 웁니다. MSXML2 :: DOMDocument60 사용하고 전체 XML을 구문 분석 할 수 있습니다. 그러나 루프 내에서 전체 프로세스를 반복하면 (200 ~ 500 회) 엄청난 메모리 누수가 발생할 수 있습니다. 나는 맵을 채우고 전체 xml을 반복 한 다음 작업 관리자에서 메모리 누수를 볼 수 있다고 설명했습니다. 릴리스 용으로 사용 된 포인터를 모두 확인했지만이 메모리 누수를 막을 수는 없습니다. MSXML6> LoadFile API 자체에 메모리 누수가 있습니까? 이것 좀 도와 주실 수 있겠습니까?MSXML6 XML 구문 분석의 메모리 누수
참고 : 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를 추가했지만 성공하지는 않았습니까? – Pankaj
당신의 논리에서, 나는'CXMLSerializer :: DeserializeRules()'가 호출되지 않는다는 것을 알았습니다 - 맞습니까? 게시물을 편집하고'SerializeRules()'에 대한 코드를 게시 할 수 있습니까? –
코드를 업데이트했습니다. – Pankaj