为啥要使用 CComBSTR 而不是只传递 WCHAR*?

Posted

技术标签:

【中文标题】为啥要使用 CComBSTR 而不是只传递 WCHAR*?【英文标题】:Why use CComBSTR instead of just passing a WCHAR*?为什么要使用 CComBSTR 而不是只传递 WCHAR*? 【发布时间】:2010-12-17 03:13:45 【问题描述】:

我是 COM 新手。替换到底有什么好处:

L"String"

CComBSTR(L"String")

我可以在我的 .NET 应用程序的 COM 部分中看到一个更改列表,其中所有字符串都以这种方式替换。想知道这个有什么需求。

【问题讨论】:

【参考方案1】:

BSTRWCHAR[] 不同。 BSTR 值以它们的长度为前缀,并且以 null 结尾。

如果您正在处理用 C 或 C++ 编写的进程内对象,您通常会侥幸成功,因为 C/C++ 代码可能会假定您的 BSTR 是一个以空字符结尾的宽字符串.

另一方面,如果您正在处理进程外/跨机器对象,则代理/存根编组代码将假定您确实通过了 BSTR,并期望找到一个长度字段(它需要这个来知道要编组多少数据)。这会大错特错。

简而言之:如果需要 BSTR,请调用 SysAllocString(或 CComBSTR,或 CString::AllocSysString)。

【讨论】:

【参考方案2】:

您可以将 L"Something" 传递给声明为期望 BSTR 的 COM 方法,但您永远不应该这样做。

约定是使用 SysAllocString() 系列函数之一分配 BSTR,并且接收 BSTR 的任何人都可以(并且应该)在想要查找字符串长度时调用 SysStringLen()。 SysStringLen() 依赖于通过 SysAllocString() 系列函数分配的 BSTR(因为它使用由这些函数分配和初始化的额外数据),如果违反该要求,程序将运行未定义的行为。

直接使用 SysAllocString() 还需要调用 SysFreeString() 来释放字符串(否则内存泄漏),因此会导致大量代码并可能导致错误。更好的方法是使用诸如 CComBSTR 或 _bstr_t 之类的包装类来管理 BSTR——它们会在必要时调用 SysAllocString()/SysFreeString()(当然,除非你滥用它们)。

【讨论】:

以上是关于为啥要使用 CComBSTR 而不是只传递 WCHAR*?的主要内容,如果未能解决你的问题,请参考以下文章

C:为啥你可以通过值传递(给函数)一个结构,而不是一个数组?

如何检查 CComBSTR 是不是以某个前缀开头?

为啥只传递 1 个参数时 argc 返回 2? [复制]

为啥要在 C++ 中按值传递对象 [重复]

为啥在直接初始化和赋值中传递 lambda 而不是复制初始化时会编译?

为啥在使用私钥加密时不能使用 RSA OAEP 填充?