gpt4 book ai didi

c++ - BSTR 中的内存泄漏到 wstring

转载 作者:行者123 更新时间:2023-11-30 01:38:07 25 4
gpt4 key购买 nike

考虑下面的代码,这里有内存泄漏吗?

HRESULT GetPath(wstring &outDomainPath)
{
CComBSTR bstrDomainPath;

AnotherGetPath(&bstrDomainPath);
outDomainPath = bstrDomainPath.Detach();
}

这有什么区别?(还是内存泄漏??)

HRESULT GetPath(wstring &outDomainPath)
{
CComBSTR bstrDomainPath;

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

最佳答案

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

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

outDomainPath = bstrDomainPath.Detach();

你调用了CComBSTR::Detach ,它释放所有权包装的 BSTR 字符串,并将此所有权转移给“其他人”。
在你的例子中,“其他人”是一个 std::wstring 对象(由 outDomainPath 引用),它不是围绕 BSTRs.

现在,考虑一下,从 C++ 类型系统的角度来看,BSTR 基本上是 wchar_t*。此外,std::wstring 实现了将 const wchar_t* 作为输入的构造函数和赋值运算符重载,假设这些原始 wchar_t 指针是 C 风格的以 NUL 结尾的字符串。因此,您可以从原始 C 风格字符串创建 std::wstring 对象。

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

但是,在您的情况下,您正在从 CComBSTR 返回的 wchar_t* (BSTR) 创建一个 wstring 对象: :分离“孤立”返回的 BSTR 字符串。

事实上,谁将负责正确释放 BSTR,调用 SysFreeString在上面? std::wstring 析构函数不会那样做。

因此,在这种情况下,您泄漏了 CComBSTR::Detach 返回的 BSTR


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

outDomainPath = bstrDomainPath;//removed detach

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

std::wstring 具有构造函数和 op= 重载以从原始 const wchar_t* NUL 终止的 C 风格字符串创建 wstring 对象.从 C++ 类型系统的角度来看,BSTR 基本上是一个 wchar_t*,因此如果您的 BSTR 包含一个以 NUL 结尾的字符串(没有 内嵌 NUL),该行代码将复制 BSTR 字符串,将其复制到 std::wstring 对象。

然后,在您的 GetPath 函数结束时,本地 CComBSTR bstrDomainPath 对象将超出范围,CComBSTR 析构函数将是由 C++ 编译器自动调用,SysFreeString 将被调用以正确释放包装的 BSTR

在这种情况下,您没有 BSTR 泄漏。

请注意,如果您没有在您的 BSTR 中嵌入 NUL,则此代码有效。在嵌入 NUL 的情况下,只有第一个 “substring” 会被复制,因为 wstring 构造函数将 const wchar_t* 作为输入在第一个 NUL 处停止。

此外,我鼓励您阅读这篇有趣的博文:

Eric Lippert's Guide to BSTR Semantics

关于c++ - BSTR 中的内存泄漏到 wstring,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48647373/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com