【问题标题】:C++ function returning BSTR for function that cannot call SysFreeString()C++ 函数为无法调用 SysFreeString() 的函数返回 BSTR
【发布时间】:2018-03-08 06:52:07
【问题描述】:

请多多包涵,我做 C++ 程序员已经有一段时间了。

我需要知道我是否做错了。它有效,但我怀疑它会导致内存泄漏。我有这个功能:

_bstr_t WCH2BSTR(wchar_t* st)
{
    BSTR stres = SysAllocString(st);
    return (_bstr_t)stres;
}

假设我要使用这样的结果:

wcout << WCH2BSTR(wCharArr) << " done." << endl;

这会导致内存泄漏,或者 BSTR 会被 Java 中的“垃圾收集器”删除吗?

如果是内存泄漏,我怎样才能在不失去作为单线的能力的情况下防止它?有时 WCH2BSTR 的结果存储在 BSTR 变量中并正确处理,但我想使用相同的函数以单行方式将 wchar_t 连接到 BSTR。

谢谢。

【问题讨论】:

  • C++ 中没有自动垃圾回收。
  • SysFreeString是使用SysAllocString的必要条件,否则你是对的,你确实会泄漏内存。
  • 首先,由于这个问题是特定于 windows 的,而不是标准的 C++,所以您可能希望将问题标记为 windows 或 microsoft(而不是 C++),以增加获得有用回复的机会。二、看MSDN,具体是docs.microsoft.com/en-us/cpp/atl-mfc-shared/…
  • @codekaizer:C++ 中有 自动垃圾收集。它与 Java 或 .NET 的垃圾收集不同之处在于它是确定性的。请记住,在 C++ 中,“自动存储持续时间” 被称为 “自动” 是有原因的。

标签: c++ windows winapi bstr


【解决方案1】:

您有内存泄漏。但它很微妙:

这一行:

BSTR stres = SysAllocString(st);

按预期分配 BSTR。

但是,return 语句:

return (_bstr_t)stres;

触发对_bstr_t(const wchar_t*) 构造函数的调用,而不是依次通过SysAllocString 分配另一个BSTR。所以你从最初的调用中泄露了一个字符串。

这可能更接近你想要的:

_bstr_t WCH2BSTR(const wchar_t* st)
{
    return _bstr_t(str);
}

_bstr_t 的构造函数会为你做 SysAllocString 的事情。 _bstr_t 的析构函数会为你做 SysFreeString 的事情。

但是...

这样说要小心:

BSTR bstr = WCH2BSTR(L"Foo");

因为那会编译!但是在分配给原始 BSTR 之后,辅助函数返回的 _bstr_t 的析构函数将被调用并释放已经返回的指针。

您真正想要做的是完全避免使用辅助函数并在您的代码中明确说明:

_bstr_t bstr = L"Foo";

当 _bstr_t 超出范围时,它所拥有的底层 BSTR 也会超出范围。

【讨论】:

  • 旁注 - 作为写这篇文章的结果,我想我刚刚发现了为什么std::string 没有明确允许自己被转换为const char*,而是强制调用者使用@ 987654329@ 方法。这是因为这样的错误会在代码中爆发。
  • 函数体可以是return st;
  • 请注意_bstr_t 有一个重载的构造函数,它接受现有的BSTRbool 来指定是否复制BSTR。因此,如果您确实调用了BSTR stres = SysAllocString(st);,您可以使用return _bstr_t(stres, false); 获取BSTR 的所有权并避免泄漏。但你说得对,return _bstr_t(st); 更好。
  • 嗯,你需要 std::wstring 而不是 std::string,是的,你可以使用它并调用 .c_str()。但是您也可以直接使用原始的 wchar_t 指针字符串和 std::wcout。我还认为,直接使用原始 wchar_t 字符串是满足您的陈述的更好方法,即“您真正想要做的就是完全避免使用辅助函数”。看我的回答。
猜你喜欢
  • 1970-01-01
  • 2017-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-31
  • 1970-01-01
  • 2018-04-14
相关资源
最近更新 更多