C++ BSTR到WSTR的内存泄漏

C++ BSTR到WSTR的内存泄漏,c++,memory-leaks,com,bstr,C++,Memory Leaks,Com,Bstr,考虑下面的代码,是否存在内存泄漏 HRESULT GetPath(wstring &outDomainPath) { CComBSTR bstrDomainPath; AnotherGetPath(&bstrDomainPath); outDomainPath = bstrDomainPath.Detach(); } 这有什么区别?(仍然存在内存泄漏??) CComBSTR是原始BSTR字符串的RAII包装 在您发布的第一个代码段中: 您调用,它将释放

考虑下面的代码,是否存在内存泄漏

HRESULT GetPath(wstring &outDomainPath)
{
    CComBSTR bstrDomainPath;

    AnotherGetPath(&bstrDomainPath);
    outDomainPath = bstrDomainPath.Detach();
}
这有什么区别?(仍然存在内存泄漏??)


CComBSTR
是原始
BSTR
字符串的RAII包装

在您发布的第一个代码段中:

您调用,它将释放已包装的
BSTR
字符串的所有权,并将此所有权转移给“其他人”。
在您的例子中,“其他人”是
std::wstring
对象(由
outDomainPath
引用),它不是
BSTR
s周围的RAII包装

现在,考虑到,从C++类型系统的角度来看,<代码> BSTR 基本上是<代码> WCARGET**/CODE >。此外,

std::wstring
实现构造函数和赋值运算符重载,将
const wchar\u t*
作为输入,假设这些原始
wchar\u t
指针是以C样式NUL结尾的字符串。因此,您可以从原始C样式字符串创建
std::wstring
对象

问题是,当调用
CComBSTR::Detach
时,原始的
BSTR
所有权被转移给调用者,调用者负责正确释放
BSTR
字符串

但是,在您的例子中,您正在从
CComBSTR::Detach
返回的
wchar\u t*
BSTR
)创建一个
wstring
对象,将返回的
BSTR
字符串“孤立”

事实上,谁将负责正确地释放调用它的
BSTR
?std::wstring析构函数不会这样做

因此,在本例中,泄漏由
ccombsr::Detach
返回的
BSTR


另一方面,在第二个代码段中:

发生的情况是编译器隐式调用,这基本上使调用方能够访问
BSTR
中包装的
CComBSTR
。请注意,在这种情况下,没有所有权转移:您只是在观察
BSTR
,它仍然属于
CComBSTR
RAII包装器

std::wstring
具有构造函数和op=重载,可从原始
const wchar\u t*
num终止的C样式字符串创建
wstring
对象<代码> BSTR 基本上是从C++类型系统透视图中的“代码> WCARAYT*<代码>,因此如果您的代码> BSTR 包含一个NUL终止的字符串(没有内嵌的NULs),那么该代码行将复制<代码> BSTR STD::WString Objult.< /P>

>在您的代码> GETPATH < /C>函数,本地的代码> CCOMBSTR BSTRMODANEPATION/COD>对象将超出范围,由C++编译器自动调用<代码> CCOMBSTR> /COD>析构函数,并调用<代码> SysFristSoG< <代码>,适当地释放包装的<代码> BSTR > 在这种情况下,您没有

BSTR
泄漏

请注意,如果您的
BSTR
中没有嵌入NUL,则此代码可以工作。对于嵌入式NUL,只会复制第一个“子字符串”,因为将
常量wchar\t*
作为输入的
wstring
构造函数将在第一个NUL处停止

此外,我鼓励您阅读以下有趣的博文:


CComBSTR
是原始
BSTR
字符串的RAII包装

在您发布的第一个代码段中:

您调用,它将释放已包装的
BSTR
字符串的所有权,并将此所有权转移给“其他人”。
在您的例子中,“其他人”是
std::wstring
对象(由
outDomainPath
引用),它不是
BSTR
s周围的RAII包装

现在,考虑到,从C++类型系统的角度来看,<代码> BSTR 基本上是<代码> WCARGET**/CODE >。此外,

std::wstring
实现构造函数和赋值运算符重载,将
const wchar\u t*
作为输入,假设这些原始
wchar\u t
指针是以C样式NUL结尾的字符串。因此,您可以从原始C样式字符串创建
std::wstring
对象

问题是,当调用
CComBSTR::Detach
时,原始的
BSTR
所有权被转移给调用者,调用者负责正确释放
BSTR
字符串

但是,在您的例子中,您正在从
CComBSTR::Detach
返回的
wchar\u t*
BSTR
)创建一个
wstring
对象,将返回的
BSTR
字符串“孤立”

事实上,谁将负责正确地释放调用它的
BSTR
?std::wstring析构函数不会这样做

因此,在本例中,泄漏由
ccombsr::Detach
返回的
BSTR


另一方面,在第二个代码段中:

发生的情况是编译器隐式调用,这基本上使调用方能够访问
BSTR
中包装的
CComBSTR
。请注意,在这种情况下,没有所有权转移:您只是在观察
BSTR
,它仍然属于
CComBSTR
RAII包装器

std::wstring
具有构造函数和op=重载,可从原始
const wchar\u t*
num终止的C样式字符串创建
wstring
对象<代码> BSTR 基本上是从C++类型系统透视图中的“代码> WCARAYT*<代码>,因此如果您的代码> BSTR 包含一个NUL终止的字符串(没有内嵌的NULs),那么该代码行将复制<代码> BSTR STD::WString Objult.< /P> 然后,在
GetPath
函数的末尾,本地
ccombstrdomainpath
对象将超出作用域,将自动调用
CComBSTR
析构函数
HRESULT GetPath(wstring &outDomainPath)
{
    CComBSTR bstrDomainPath;

    AnotherGetPath(&bstrDomainPath);
    outDomainPath = bstrDomainPath;//removed detach
}
outDomainPath = bstrDomainPath.Detach();
outDomainPath = bstrDomainPath;//removed detach