C++,COM和传递字符串

Jus*_*tin 0 c++ string com exception bstr

我正在调试其他程序员的Windows Media Player插件的源代码.这个插件有时会导致WMP崩溃,有时打开插件设置窗口需要很长时间.仅在播放音乐时打开设置窗口时才会出现此问题.如果播放器停止,它会立即打开.

在查看代码和调试时,我已经找到了代码行,这似乎是导致问题的原因.

属性页面具有以下成员变量:

CComPtr<IDsp_plugin> m_pDsp_plugin;
Run Code Online (Sandbox Code Playgroud)

初始化时的属性页调用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);
Run Code Online (Sandbox Code Playgroud)

此时,hres是"0x80010105:服务器引发异常." 和Visual Studio Debug输出显示"wmplayer.exe中0x764efbae的第一次机会异常:0x80010105:

get_text方法定义如下:

在Dsp_plugin.idl中

interface IDsp_plugin : IUnknown
{
    HRESULT get_text([out] unsigned char* *pVal);
...
Run Code Online (Sandbox Code Playgroud)

在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);
...
Run Code Online (Sandbox Code Playgroud)

最后抛出此异常的方法本身: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;
}
Run Code Online (Sandbox Code Playgroud)

使用设置"使用Unicode字符集"编译COM DLL.

我不是经验丰富的COM程序员,但是将字符串作为unsigned char**传递给我似乎不寻常,我在处理COM时看到的主要是BSTR或VARIANT.

也许一些COM大师可以解释,为什么会发生这种异常并且可以通过将方法转换为使用BSTR*和SysAllocString/SysfreeString而不是unsigned char**/malloc/free来修复它?

bdo*_*lan 5

简而言之,COM不知道如何传递类型的指针unsigned char *.该默认编组规则被应用(因为接口定义没有指定任何参数属性),并且,如果我正确地解释这一点,COM编组外指针本身txt正常,但对待*txt作为一个指向单一的 unsigned char,而不是字符串.

如果呼叫者和被叫者碰巧在同一个公寓中,这仍然可以工作; 从它的声音来看,它们不是.

最简单的解决方案就是将参数设为a BSTR *.COM具有特殊处理功能BSTR,可确保正确传递.