2017-07-13 19 views
0

埋め込みWebブラウザコントロールにHTML文字列をロードする次のコードがあります。このコードでは、GlobalFreeというエラーが表示されます(私はそれをマークしています)。デバッガは単純に言う:TestProgram.exe has triggered a breakpoint、他の説明はありません。GlobalFreeはエラーを示します。デバッガは説明しません

エラーラインにコメントすると、プログラムが正常に実行され、ブラウザコントロールがHTML文字列を正常にロードします。しかし、私はそれをコメントすると、私のアプリは確かにメモリリークになる。

ここで正確な問題は何ですか?どのように修正できますか?

私の環境:

OS:Windowsの10
IDE:Visual Studioのコミュニティ2017
コンパイラツールセット:V120

コード:

HRESULT STDMETHODCALLTYPE WebBrowser::displayHTMLStr(LPCTSTR htmlSource) { 
    HRESULT     hr; 

    IDispatch     *pDispatch = 0; 
    IHTMLDocument2   *pHtmlDoc2 = 0; 
    IPersistStreamInit  *pPSI = 0; 
    IStream     *pStream = 0; 
    HGLOBAL     hHTMLContent; 

    hr = webBrowser2->get_Document(&pDispatch); 
    if (FAILED(hr) || !pDispatch) { 
     goto displayHTMLStr_clean; 
    } 

    hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **)&pHtmlDoc2); 
    if (FAILED(hr) || !pHtmlDoc2) { 
     goto displayHTMLStr_clean; 
    } 

    hr = pHtmlDoc2->QueryInterface(IID_IPersistStreamInit, (void **)&pPSI); 
    if (FAILED(hr) || !pPSI) { 
     goto displayHTMLStr_clean; 
    } 







    // allocate global memory to copy the HTML content to 
    hHTMLContent = ::GlobalAlloc(GPTR, (::wcslen(htmlSource) + 1) * sizeof(TCHAR)); 
    if (!hHTMLContent) { 
     hr = E_OUTOFMEMORY; 
     goto displayHTMLStr_clean; 
    } 

    ::wcscpy((TCHAR *)hHTMLContent, htmlSource); 

    // create a stream object based on the HTML content 
    hr = ::CreateStreamOnHGlobal(hHTMLContent, TRUE, &pStream); 
    if (FAILED(hr) || !pStream) { 
     goto displayHTMLStr_clean; 
    } 

    hr = pPSI->InitNew(); 
    if (FAILED(hr)) { 
     goto displayHTMLStr_clean; 
    } 

    hr = pPSI->Load(pStream); 
    displayHTMLStr_clean: 

    if (pStream) { 
     pStream->Release(); 
    } 
    if (hHTMLContent) { 
     GlobalFree(hHTMLContent);      // <------ Error here 
    } 
    if (pPSI) { 
     pPSI->Release(); 
    } 
    if (pHtmlDoc2) { 
     pHtmlDoc2->Release(); 
    } 
    if (pDispatch) { 
     pDispatch->Release(); 
    } 

    return hr; 
} 
+0

を?あなたがたぶんそこにいくつかのブレークポイントがあります。 – ForceBru

+0

'GlobalFree'は' CreateStreamOnHGlobal'が作成したメモリを解放します。いいえ。私はその行にブレークポイントを設定しません。 – Sakura

答えて

3

あなたが渡して、CreateStreamOnHGlobalを呼んでいますTRUEfDeleteOnReleaseパラメータ。これにより、メモリの所有権がIStream実装に転送されます。最終リリースでは、hGlobalパラメータで参照されるメモリが解放されます。 IStreamオブジェクトが解放された後で、再度そのハンドルでGlobalFreeを呼び出すと、ダブルフリーのバグです。 fDeleteOnReleaseパラメータとして

  1. パスFALSE

    は、二つの解決策があります。

  2. GlobalFreeへの呼び出しを削除します。さておき、CreateStreamOnHGlobalに渡されるメモリへのハンドルを可動として割り当てなければならないよう

ハンドルが可動とnondiscardableとして割り当てなければなりません。


それは、 SHCreateMemStreamを呼び出すことも可能です - "優れたパフォーマンス生成" - MSDNによると: `GlobalFree`何

IStream* pStream = ::SHCreateMemStream(reinterpret_cast<const BYTE*>(htmlSource), 
             _tcslen(htmlSource) * sizeof(TCHAR)); 
関連する問題