c++ - 将 VARIANT 从 COM 编码回 C++ 客户端

标签 c++ com marshalling atl

我正在尝试将来自 COM 对象的 BSTR 安全数组编码回 C++ 客户端应用程序。

涉及函数的IDL定义:

[id(5), helpstring("method GetStreams")] 
    HRESULT GetStreams( [out,retval] VARIANT* pvarStreamNames );

这是我对 GetStreams() 函数的实现:

STDMETHODIMP CArchiveManager::GetStreams(VARIANT* pvarStreamNames)
{   
CComSafeArray<BSTR, VT_BSTR>    saStreamNames;
CComVariant                     varOutNames;

Stream* pNext       = NULL;
int     nNumStreams = m_Streams.NumStreams();

if( nNumStreams == 0 )
    return S_OK;

for(int x = 0; x < nNumStreams; x++)
{
    pNext = m_Streams.GetAt(x); 
    if( pNext )             
        saStreamNames.Add( pNext->StreamName() );   
}

if( saStreamNames.GetCount() > 0 )
{
    varOutNames.vt      = VT_ARRAY;
    varOutNames.parray  = saStreamNames.m_psa;

    varOutNames.Detach(pvarStreamNames);
}

return S_OK;
}

C++ 客户端程序调用 GetStreams() 函数的方式如下:

VARIANT varStreamNames;
hr = spArchiveMgr->GetStreams( &varStreamNames );

我使用交互式调试器跟踪整个程序,一切似乎都正常工作(safearray 正确填充等),直到 GetStreams() 函数返回。那时,我收到一条“未处理的异常读取位置”消息。

有关如何调试/解决此问题的建议?

最佳答案

有两个问题。第一个是

 VARIANT varStreamNames;

是单元化的,所以当

varOutNames.Detach(pvarStreamNames);

运行它调用VariantClear()在未初始化的变量上,这会导致未定义的行为 - 您的程序崩溃。

您必须调用 VariantInit()varStreamNames在调用 COM 方法之前或只使用 CComVariant输入 varStreamNames .

第二个是:

CComSafeArray<BSTR, VT_BSTR>    saStreamNames;
CComVariant                     varOutNames;

varOutNames.vt      = VT_ARRAY;
varOutNames.parray  = saStreamNames.m_psa;

执行安全数组的浅拷贝 - 现在都是 saStreamNamesvarOutNames拥有安全阵列等saStreamNames在释放安全数组的范围末尾被销毁。

由于您已将相同的安全数组地址复制到 pvarStreamNames 中你现在有一个带有悬空安全数组指针的变体。尝试访问该安全数组是未定义的行为。你应该使用 Detach() CComSafeArray的方法|释放所有权。

关于c++ - 将 VARIANT 从 COM 编码回 C++ 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4204488/

相关文章:

c++ - 在C++中调用成员函数而不创建对象

.net - COM 多线程支持

C#调用具有复杂结构的deviceIOControl

c++ - DirectShow 解码器减少媒体时间

c++ - CComPtrBase::~CComPtrBase 在解除分配智能指针时崩溃

c# - MessageBox.Show() 是否自动编码到 UI 线程?

java - 如何在 JAXB 中获取输出(编码(marshal)处理)?

c++ - 我可以从 Visual Studio C++ 跨平台库项目创建动态框架吗?

c++ - Z 缓冲区导致无法绘制

c++ - 将数字 vector 从基数转换为基数