使用_bstr_t在函数中传递BSTR*类型的参数
执行此操作的正确方法是什么:
_bstr_t description;
errorInfo->GetDescription( &description.GetBSTR() );
或:
_bstr_t description;
errorInfo->GetDescription( description.GetAddress() );
其中 IError:GetDescription
定义为:
HRESULT GetDescription (BSTR *pbstrDescription);
我知道我可以轻松做到这一点:
BSTR description= SysAllocString (L"Whateva"));
errorInfo->GetDescription (&description);
SysFreeString (description);
谢谢
What is the correct way of doing this:
_bstr_t description;
errorInfo->GetDescription( &description.GetBSTR() );
or:
_bstr_t description;
errorInfo->GetDescription( description.GetAddress() );
Where IError:GetDescription
is defined as:
HRESULT GetDescription (BSTR *pbstrDescription);
I know I could easily do this:
BSTR description= SysAllocString (L"Whateva"));
errorInfo->GetDescription (&description);
SysFreeString (description);
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
BSTR 是引用计数的,我严重怀疑如果您使用 GetAddress(),它是否能正常工作。遗憾的是,无法使用源代码来仔细检查这一点。我一直都是这样做的:
The BSTR is reference counted, I seriously doubt that will work right if you use GetAddress(). Sadly the source code isn't available to double-check that. I've always done it like this:
跟进 @Hans 的答案 - 构造
_bstr_t
的适当方法取决于GetDescription
是否返回您拥有的BSTR
,或者一个引用您不必释放的内存。这里的目标是最大限度地减少副本数量,同时避免对返回数据进行任何手动调用
SysFreeString
。我将修改所示的代码以澄清这一点:To follow up on @Hans's answer - the appropriate way to construct the
_bstr_t
depends on whetherGetDescription
returns you aBSTR
that you own, or one that references memory you don't have to free.The goal here is to minimize the number of copies, but also avoid any manual calls to
SysFreeString
on the returned data. I would modify the code as shown to clarify this:较晚的答案可能不适用于早期(或更高)版本的 Visual Studio;然而,
VS 12.0 具有内联
_bstr_t
实现,并且显然在调用GetBSTR() 时会创建一个
处女Data_t
实例,其m_RefCount
为 1_bstr_t
。因此,第一个示例中的_bstr_t
生命周期看起来没问题:但是如果
_bstr_t
脏了,现有的内部m_wstr
指针将被覆盖,泄漏它引用的前一个内存。通过使用以下
operator&
,可以使用脏_bstr_t
,因为它首先是通过Assign(nullptr)
清除的。重载还提供了使用地址运算符代替GetBSTR()
的便利;因此,您的第一个示例可能如下所示:
此评估基于 VS 12.0 中的
comutil.h
。A late answer that may not apply to earlier (or later) versions of Visual Studio; however,
VS 12.0 has the
_bstr_t
implementation inline, and evidently an internalData_t
instance is created with am_RefCount
of 1 when callingGetBSTR()
on a virgin_bstr_t
. So the_bstr_t
lifecycle in your first example looks to be okay:But if
_bstr_t
is dirty, the existing internalm_wstr
pointer will be overwritten, leaking the previous memory it referenced.By using the following
operator&
, a dirty_bstr_t
can be used given that it's first cleared viaAssign(nullptr)
. The overload also provides the convenience of utilizing the address operator instead ofGetBSTR()
;So, your first example could instead look like the following:
This evaluation was based on
comutil.h
from VS 12.0._bstr_t(及其 ATL 兄弟 CComBSTR)是 BSTR 的资源所有者。从代码中观察,“GetAddress”似乎是专门为使用 BSTR 输出参数的用例而设计的,其中客户端获得所有权并期望释放 BSTR。 MSDN 指出:“释放任何现有字符串并返回新分配的字符串的地址。”。
请注意,如果 _bstr_t 已经拥有 BSTR,则使用“GetAddress()”并不等同于使用“&GetBSTR()”。 “GetBSTR”仅返回商店位置,而不释放现有位置。
注意:文档中没有说明“GetAddress”的具体用例;这是我通过查看源代码和使用 ATL 对应部分 CComBSTR 的经验得出的结论。
由于用户“caoanan”对此解决方案提出质疑,我将 Microsoft 的源代码粘贴到此处:
_bstr_t (and its ATL sibling CComBSTR) are resource owners of BSTR. Spying from the code it seems that 'GetAddress' is specifically designed for the use case of working with BSTR output parameters where client takes ownership and expected to free the BSTR. MSDN states: 'Frees any existing string and returns the address of a newly allocated string.'.
Note that using 'GetAddress()' is not equivalent to using '&GetBSTR()' in case the _bstr_t already owns a BSTR. 'GetBSTR'' only returns the store location without freeing an existing one.
Caveat: this specific use case of 'GetAddress' is not stated in the documentation; it is my deduction from looking at the source code and experience with its ATL counter part CComBSTR.
Since user 'caoanan' questioned this solution, I paste here the source code Microsoft:
感谢 bvj 和 Gast128 的回答,很明显,您可以通过
GetAddress()
将空的bstr_t
传递给具有签名GetDescription(BSTR* BS)
,这将创建一个新的BSTR
,但您绝不能以这种方式将包含值的bstr_t
传递给函数旨在使用包装的BSTR
,因为GetAddress()
将释放包装的BSTR
。我给出一个完整的例子。Thanks to the answers by bvj and gast128, it is clear that you can pass an empty
bstr_t
viaGetAddress()
to a function with the signatureGetDescription(BSTR* BS)
, which will create a newBSTR
, but you must never pass abstr_t
containing a value in this way to a function intended to use the wrappedBSTR
, sinceGetAddress()
will free the wrappedBSTR
. I present a complete example.