首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MSXML6 XML解析中的内存泄漏

MSXML6 XML解析中的内存泄漏
EN

Stack Overflow用户
提问于 2014-01-06 22:31:55
回答 2查看 2K关注 0票数 0

我已经编写了MFC DLL来加载XML文件或XML字符串并对其进行解析。它用xml元素填充一个映射。我使用的是MSXML2::DOMDocument60,可以解析整个xml。但是如果我在循环中迭代整个过程(200-500次),我可以看到巨大的内存泄漏。我注释了填充映射并迭代了整个xml,然后只有我可以在任务管理器中看到内存泄漏。我检查了所有用于释放的指针,但无法阻止内存泄漏。MSXML6 > LoadFile应用程序接口本身是否存在内存泄漏?你能帮个忙吗?

注意:我在Init方法中初始化了COM,在Dispose方法中取消了它的初始化。此代码。这些方法在下面的代码中没有提到。

代码:

C++ DLL:

代码语言:javascript
复制
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#测试应用程序:

代码语言:javascript
复制
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();
EN

回答 2

Stack Overflow用户

发布于 2014-01-06 23:07:09

您需要在for循环的末尾释放pIDOMNode()

不太确定为什么你的一些变量需要是static的,它们不会占用太多的空间(在我看来它们只是指针)……

票数 0
EN

Stack Overflow用户

发布于 2014-01-07 20:01:06

我可以通过释放BSTR分配的内存来解决这个问题。由于BSTR是一个原始指针,我们需要使用SysFreeString MSDN来释放内存。添加SysFreeString后,我可以看到稳定的内存。我们也可以将BSTR替换为_bstr_t,它的工作方式类似于智能指针。当变量超出作用域时,它会释放内存。谢谢你的帮助!!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20952179

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档