C++ MSXML2::IXMLDOMDocument2Ptr->;GetXML()搞乱了我的字符串!

C++ MSXML2::IXMLDOMDocument2Ptr->;GetXML()搞乱了我的字符串!,c++,msxml,C++,Msxml,全部, 这是我的密码 //declare string pointer BSTR markup; //initialize markup to some well formed XML <- //declare and initialize XML Document MSXML2::IXMLDOMDocument2Ptr pXMLDoc; HRESULT hr; hr = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));

全部,

这是我的密码

//declare string pointer
BSTR markup;

//initialize markup to some well formed XML <-

//declare and initialize XML Document
MSXML2::IXMLDOMDocument2Ptr pXMLDoc;
HRESULT hr;
hr = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));
pXMLDoc->async = VARIANT_FALSE;
pXMLDoc->validateOnParse = VARIANT_TRUE;
pXMLDoc->preserveWhiteSpace = VARIANT_TRUE;    

//load markup into XML document
vtBoolResult = pXMLDoc->loadXML(markup);

//do some changes to the XML file<-

//get back string from XML doc
markup = pXMLDoc->Getxml(); //<-- this retrieves RUBBISH
但我还是得到了同样的结果

即使我调用GetXML()而不更改xml文档中的任何内容,我仍然会得到垃圾

此时,如果我尝试将损坏的指针分配给另一个指针,它将出错:

试图恢复写保护 记忆。这通常是一个迹象 另一个内存已损坏

有什么建议吗

编辑1:

我发现这与XML字符串的大小有关。 如果它发生在给定的XML字符串上,并且我减小了大小(保持相同的模式),那么它就可以正常工作。看起来MSXML2::DOMDocument40对大小有限制? 具体来说,如果我有超过16407个字符,就会发生这种情况。我还有一个GetXML将检索垃圾-如果是请尝试替换

 BSTR Markup;

BSTR几乎是一个哑指针,我认为GetXML()的返回结果正在被转换成一个临时指针,当您看到它时,它就会被销毁。bstr\u t用一些聪明的指针来包装它


注意:你的“超值”并没有按照我的建议做。同样,BSTR只是一个指针,并不“拥有”它所指向的内容。从另一方面来说,是的。我认为GetXML()函数返回了一个bstr\u t,当它超出范围时将被删除,使bstr指向不再有效的内存

好吧,我认为帕特里克是对的。我获取了您的代码并创建了一个名为getxmltest的快速ATL EXE项目。 我在#include指令之后添加了这一行

#import "MSXML3.DLL"
删除了注册组件的生成后事件,因为我不想从exe中公开任何组件,但只想引用所有ATL标头和LIB,并将以下代码添加到_tWinMain

extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, 
                                LPTSTR /*lpCmdLine*/, int nShowCmd)
{
    CoInitialize(NULL);
    {
        //declare string pointer
        _bstr_t                     markup;
        //initialize markup to some well formed XML <-
        //declare and initialize XML Document
        MSXML2::IXMLDOMDocument2Ptr pXMLDoc;
        HRESULT                     hr              = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument));

        pXMLDoc->async              = VARIANT_FALSE;
        pXMLDoc->validateOnParse    = VARIANT_TRUE;
        pXMLDoc->preserveWhiteSpace = VARIANT_TRUE;    

        //load markup into XML document
        VARIANT_BOOL                vtBoolResult    = pXMLDoc->loadXML(L"<XML></XML>");

        //do some changes to the XML file<-
        //get back string from XML doc
        markup = pXMLDoc->Getxml(); //<-- this retrieves RUBBISH (not anymore...)
        ATLTRACE("%S", (BSTR)markup.GetBSTR());
    }
    CoUninitialize();
    return _AtlModule.WinMain(nShowCmd);
}
WINAPI内部的外部“C”tWinMain(HINSTANCE/*HINSTANCE*/,HINSTANCE/*hPrevInstance*/, LPTSTR/*lpCmdLine*/,int nShowCmd) { 共初始化(空); { //声明字符串指针 _bstr\t标记; //将标记初始化为某种格式良好的XML async=VARIANT\u FALSE; pXMLDoc->validateOnParse=VARIANT\u TRUE; pXMLDoc->preserveWhiteSpace=VARIANT\u TRUE; //将标记加载到XML文档中 VARIANT_BOOL vtBoolResult=pXMLDoc->loadXML(L“”);
//对XML fileGetxml()进行一些更改;//但是,我不熟悉这个特定的XML库:

这里需要注意的是,最初的问题是在变量“markup”检索结果时重写该变量。许多XML解析器返回指向初始输入(即标记)的指针,因此当您将其替换为输出时,您也会删除XML解析器的输入

这个过程可能会使您刚刚收到的字符串无效,您会注意到Eugenio Miró在他的示例中没有犯这个错误,因为他分配了一个不同的变量来保存输入(pXMLDoc)

你可能想做的一个快速测试是改变

//get back string from XML doc
markup = pXMLDoc->Getxml(); //<-- this retrieves RUBBISH
//从XML文档中获取字符串

markup=pXMLDoc->Getxml();///Getxml();//这是我之前编写的代码,稍加修改,添加了20000个“child”元素:),效果很好

extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, 
                                LPTSTR /*lpCmdLine*/, int nShowCmd)
{
    CoInitialize(NULL);
    {
        //declare string pointer
        _bstr_t                           markup;
        //initialize markup to some well formed XML <-
        //declare and initialize XML Document
        try {
            MSXML2::IXMLDOMDocument2Ptr   pXMLDoc;
            HRESULT                       hr              = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument));    
            pXMLDoc->async                = VARIANT_FALSE;
            pXMLDoc->validateOnParse      = VARIANT_TRUE;
            pXMLDoc->preserveWhiteSpace   = VARIANT_TRUE;    

            //load markup into XML document
            VARIANT_BOOL                  vtBoolResult    = pXMLDoc->loadXML(L"<XML></XML>");

            for (int i = 0; i < 20000; i++) {
                MSXML2::IXMLDOMNodePtr    node            = pXMLDoc->createNode(_variant_t("element"), _bstr_t("child"), _bstr_t(""));

                if (node)
                    pXMLDoc->documentElement->appendChild(node);
            }

            //do some changes to the XML file<-
            //get back string from XML doc
            markup = pXMLDoc->Getxml(); //<-- th
            ATLTRACE("XML lenght = %d, xml=%S\n", markup.length(), (BSTR)markup.GetBSTR());
        } catch(_com_error e) {
            ATLTRACE("error = %S\n", (BSTR)e.ErrorMessage());
        }
    }
    CoUninitialize();
    return _AtlModule.WinMain(nShowCmd);
}
WINAPI内部的外部“C”tWinMain(HINSTANCE/*HINSTANCE*/,HINSTANCE/*hPrevInstance*/, LPTSTR/*lpCmdLine*/,int nShowCmd) { 共初始化(空); { //声明字符串指针 _bstr\t标记; //将标记初始化为某种格式良好的XML async=VARIANT\u FALSE; pXMLDoc->validateOnParse=VARIANT\u TRUE; pXMLDoc->preserveWhiteSpace=VARIANT\u TRUE; //将标记加载到XML文档中 VARIANT_BOOL vtBoolResult=pXMLDoc->loadXML(L“”); 对于(int i=0;i<20000;i++){ MSXML2::IXMLDOMNodePtr node=pXMLDoc->createNode(_variant_t(“元素”)、_bstr_t(“子”)、_bstr_t(“”); 如果(节点) pXMLDoc->documentElement->appendChild(节点); }
//对XML fileGetxml()进行一些更改//我尝试了以下方法:bstr_t superMarkup=bstr_t(标记);然后在LoadXML调用中使用superMarkup而不是标记。没有任何更改!有两个变量,一个是bstr_t initialXML,一个是bstr_t returnedXML。仅将每个变量用于一个目的。如果您不完全理解bstr和bstr_t(因此,谁(如果有的话)拥有包含GetXML结果的内存),这可能也取决于月亮的相位。我不能提供更多的帮助。即使我理解BSTR BSTR\t,你想要的一切,如果大小正好低于16407,它仍然没有意义。无论如何,我尝试过用BSTR\t替换BSTR,如果大小低于那个神奇的数字,它也可以正常工作,完全相同作为我的原始代码,谢谢你指出这一点,但我不理解你对pXMLDoc的考虑!请重新阅读我的帖子。除非你100%理解BSTR的工作原理,否则你需要完全抛弃它。你能建议一段代码来实现你的解决方案,以便我通过示例理解吗?如果大小>16407,你能重现我的问题吗(请参见OP中的编辑)我在代码中添加了几行代码,以便向xml动态添加元素,从而获得长度为160013字节的xml,这一点没有问题
'getxmltest.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6001.18000_none_5cdbaa5a083979cc\comctl32.dll'
<XML></XML>
'getxmltest.exe': Unloaded 'C:\Windows\SysWOW64\msxml3.dll'
The program '[6040] getxmltest.exe: Native' has exited with code 0 (0x0).
//get back string from XML doc
markup = pXMLDoc->Getxml(); //<-- this retrieves RUBBISH
//get back string from XML doc
BSTR output = pXMLDoc->Getxml(); //<-- perhaps this doesn't
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, 
                                LPTSTR /*lpCmdLine*/, int nShowCmd)
{
    CoInitialize(NULL);
    {
        //declare string pointer
        _bstr_t                           markup;
        //initialize markup to some well formed XML <-
        //declare and initialize XML Document
        try {
            MSXML2::IXMLDOMDocument2Ptr   pXMLDoc;
            HRESULT                       hr              = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument));    
            pXMLDoc->async                = VARIANT_FALSE;
            pXMLDoc->validateOnParse      = VARIANT_TRUE;
            pXMLDoc->preserveWhiteSpace   = VARIANT_TRUE;    

            //load markup into XML document
            VARIANT_BOOL                  vtBoolResult    = pXMLDoc->loadXML(L"<XML></XML>");

            for (int i = 0; i < 20000; i++) {
                MSXML2::IXMLDOMNodePtr    node            = pXMLDoc->createNode(_variant_t("element"), _bstr_t("child"), _bstr_t(""));

                if (node)
                    pXMLDoc->documentElement->appendChild(node);
            }

            //do some changes to the XML file<-
            //get back string from XML doc
            markup = pXMLDoc->Getxml(); //<-- th
            ATLTRACE("XML lenght = %d, xml=%S\n", markup.length(), (BSTR)markup.GetBSTR());
        } catch(_com_error e) {
            ATLTRACE("error = %S\n", (BSTR)e.ErrorMessage());
        }
    }
    CoUninitialize();
    return _AtlModule.WinMain(nShowCmd);
}
'getxmltest.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6001.18000_none_5cdbaa5a083979cc\comctl32.dll'
XML lenght = 160013, xml=<XML><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><'getxmltest.exe': Unloaded 'C:\Windows\SysWOW64\msxml3.dll'
The program '[4884] getxmltest.exe: Native' has exited with code 0 (0x0).