2

全て、

これは私のコードです

//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

この時点で、私の文字列は壊れています (最初の数文字だけで、その後ゴミになります)。エンコードの問題のようです。

私も次のことを試しました:

_bstr_t superMarkup = _bstr_t(markup);

//did my stuff

superMarkup = pXMLDoc->Getxml();

markup = superMarkup; 

それでも私は同じ結果を得ています。

xml ドキュメントで何も変更せずに GetXML() を呼び出しても、まだゴミになります。

この時点で、破損したポインターを別のポインターに割り当てようとすると、エラーが発生します。

書き込み保護されたメモリを復元しようとしました。これは多くの場合、他のメモリが破損していることを示しています。

なにか提案を?

EDIT1:

これは、XML 文字列のサイズに関連して発生していることがわかりました。特定の XML 文字列で発生し、(同じスキーマを維持して) サイズを小さくすると、問題なく動作します。MSXML2::DOMDocument40 にはサイズ制限があるように見えますか? 詳細には、16407 文字を超えると発生します。RUBBISH を取得する GetXML がもう 1 つあります。それが <= 16407 であれば、すべて正常に動作します。

EDIT2:

ロディは正しかった - 私はそれ_bstr_tがクラスであることを見逃していました...

ベルを鳴らしますか?

乾杯

4

4 に答える 4

4

交換してみる

 BSTR Markup;

 bstr_t Markup;

BSTR はほとんどばかげたポインターであり、GetXML() の戻り結果は一時的なものに変換されており、それが表示されるまでに破棄されていると思います。bstr_t はそれをいくつかのスマート ポインターの利点でラップします...

注:あなたの「スーパーマークアップ」は、私が提案したことをしませんでした。繰り返しますが、 BSTR は単なるポインターであり、それが指すものを "所有" しません。一方、bstr_t はそうします。あなたの GetXML() 関数は bstr_t を返していると思いますが、これは範囲外になると削除され、BSTR は無効になったメモリを指したままになります。

于 2008-11-27T17:46:54.297 に答える
1

これは私が以前に書いたコードで、20000の「子」要素を追加する少しの変更を加えたものです:)そしてそれはうまく機能します。

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

これにより、デバッガーで1024の出力行が生成されますが、必要に応じてxmlをstdoutputに簡単に出力できます。これは私がこれまでに得た出力です

'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).
于 2008-12-05T13:52:20.087 に答える
1

ただし、この特定の xml ライブラリには精通していません。

ここで注意すべきことは、元の質問が結果を取得したときに変数「マークアップ」を上書きしたことです。多くの XML パーサーは初期入力 (マークアップ) へのポインターを返すため、それを出力に置き換えると、XML パーサーへの入力も削除されます。

このプロセスにより、受信したばかりの文字列が無効になる可能性があります。Eugenio Miró は、入力 (pXMLDoc) を保持するために別の変数を割り当てているため、この例ではこの間違いを犯していないことに気付くでしょう。

あなたがやりたいかもしれない簡単なテストは、変更することです

//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

そして、それが違いを生むかどうかを確認してください。

于 2008-11-27T20:21:25.233 に答える
1

わかりました、パトリックは正しいと思います。あなたのコードを使用して、getxmltest という名前の簡単な ATL EXE プロジェクトを作成しました。#include ディレクティブの後にこの行を追加しました

#import "MSXML3.DLL"

exeからコンポーネントを公開したくないが、すべてのATLヘッダーとライブラリのみが既に参照されているため、コンポーネントを登録するビルド後のイベントを削除し、次のコードを_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);
}

結果のトレース行は次のとおりでした...

'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).

最初に入力した文字列を確認できる場所.. MSXML エンジンで処理した結果の xml を表示するには、これで十分だと思ったので、コードにロジックを追加しませんでした。明らかに、このコードを使用してさらにテストを行い、次に何が起こるかを確認できます。

于 2008-11-27T18:54:00.777 に答える