2014-01-06 3 views
0

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(); 

답변

0

당신은을위한 루프의 끝에서 pIDOMNode()을 해제해야합니다. 나는이 문제를 해결할 수

+0

답장을 보내 주신 에드워드 감사합니다. for 루프의 끝에는 릴리스 pIDOMNode를 추가했지만 성공하지는 않았습니까? – Pankaj

+0

당신의 논리에서, 나는'CXMLSerializer :: DeserializeRules()'가 호출되지 않는다는 것을 알았습니다 - 맞습니까? 게시물을 편집하고'SerializeRules()'에 대한 코드를 게시 할 수 있습니까? –

+0

코드를 업데이트했습니다. – Pankaj

0

당신의 변수 중 일부는 static를해야하는 이유, 그들은 (그들은 단지까지 내가 볼 수있는 포인터) 많은 공간을 차지하지 않는 대해 매우 확실하지 ... BSTR에 의해 할당 된 메모리를 해제합니다. BSTR은 미처리 포인터이기 때문에 SysFreeString MSDN을 사용하여 메모리를 비울 필요가 있습니다. SysFreeString을 추가 한 후에 안정적인 메모리를 볼 수있었습니다. 또한 BSTR을 스마트 포인터처럼 작동하는 _bstr_t로 바꿀 수 있습니다. 변수가 범위를 벗어날 때 메모리를 할당 해제합니다. 모든 도움에 감사드립니다 !!