2011-07-19 70 views
0

我正在調試Windows Media Player插件的其他程序員的源代碼。這個插件有時會導致WMP崩潰,有時需要很長時間才能打開插件設置窗口。只有在播放音樂時打開設置窗口才會出現問題。如果玩家停止,它將不會出現問題。C++,COM和傳遞字符串

在查看代碼和調試過程中,我看到了代碼行,這似乎是導致問題的原因。

的屬性頁具有以下成員變量:

CComPtr<IDsp_plugin> m_pDsp_plugin; 

,並在初始化屬性頁調用COM對象的get_text方法:

unsigned char * txt = NULL; 
//m_pDsp_plugin is a valid pointer to IDsp_plugin 
HRESULT res = m_pDsp_plugin->get_text(&txt); 

此時HRES是「0x80010105:該服務器拋出異常。「和Visual Studio調試輸出顯示「在0x764efbae第一次機會異常在wmplayer.exe:0x80010105:

get_text方法被定義如下:

在Dsp_plugin.idl

interface IDsp_plugin : IUnknown 
{ 
    HRESULT get_text([out] unsigned char* *pVal); 
... 

在Dsp_plugin.h

class ATL_NO_VTABLE CDsp_plugin : 
    public CComObjectRootEx<CComMultiThreadModel>, 
    public CComCoClass<CDsp_plugin, &CLSID_Dsp_plugin>, 
    public IDsp_plugin, 
    public IMediaObject, 
    public IWMPPluginEnable, 
    public ISpecifyPropertyPages 
{ 

    STDMETHOD(get_text)(unsigned char* *txt); 
... 

最後會拋出該異常的方法本身: Dsp_plugin.cpp

STDMETHODIMP CDsp_plugin::get_text (unsigned char* *txt) 
{ 
    ... // some code for copying a valid string from somewhere to char* y 
    // 11 bytes of memory for y was allocated using malloc(10+1); 
    // y contains a valid C string here, tested with debugger and passing to OutputDebugStringA 

    *txt = (unsigned char*)(y); // This line executes normally, but at the end the caller gets "The server threw an exception." and WMP starts behaving weirdly. 
           // If I comment it out, the caller gets S_OK and there are no any issues with WMP. 

    return S_OK; 
} 

COM DLL通過設置「使用Unicode字符集」進行編譯。

我沒有經驗的COM程序員,但作爲無符號字符**傳遞字符串似乎不尋常的我,我在處理COM時看到大多數BSTR或VARIANT。

也許一些COM大師可以解釋爲什麼會發生這種異常,並且可以通過將方法轉換爲使用BSTR *和SysAllocString/SysfreeString而不是unsigned char **/malloc/free來解決這個問題?

回答

5

簡而言之,COM不知道如何傳遞類型爲unsigned char *的指針。應用default marshalling rules(因爲接口定義沒有指定任何參數屬性),並且,如果我正確解釋此錯誤,COM將外部指針本身編組爲txt正確,但將*txt作爲指向單一 的指針,不是一個字符串。

如果主叫方和被叫方恰好在同一個房間內,這可能仍然有效;從它的聲音來看,它們不是。

最簡單的解決方法是簡單地將參數設置爲BSTR *。 COM有BSTR的特殊處理,這將確保它正確傳遞。