【问题标题】:Pass wchar_t instead of BSTR causes E_OUTOFMEMORY error传递 wchar_t 而不是 BSTR 会导致 E_OUTOFMEMORY 错误
【发布时间】:2021-08-24 14:17:58
【问题描述】:

我有一个简单的 DirectShow 库,并且我还有一个客户端应用程序可以调用该库中的函数。问题是某些函数接受BSTR 作为参数,但我更喜欢传递std::stringchar*。可以肯定的是,如果我使用其中一种类型,我会得到很多编译器错误。

我问了原因,有人说我不能使用它们,因为它们不像 BSTR 那样保证 ABI。

我也试过wchar_t。我将它传递给我的函数而不是 BSTR。令人惊讶的是它没有产生任何编译器错误:

std::string username = "john";
wchar_t wcstring[4] = {0};
MultiByteToWideChar(0, 0, username.c_str(), 4, wcstring, 4);

但是当我调用我的函数时:

HRESULT hr = pFoo->myDummyFunction(wcstring);

然后运行程序,它返回 E_OUTOFMEMORY 作为 HRESULT。我很想知道为什么会这样。

【问题讨论】:

  • 你知道 C++ 中的字符串真的被称为 null-terminated 字符串吗?有效的字符串必须包含结尾的空终止符。
  • @Someprogrammerdude 你的意思是我应该将空终止符附加到 wcstring 的末尾?
  • docuemtation 明确警告不要将wchar_t* 用作BSTR
  • @linarcx 你知道吗,字符序列"john" 需要5 存储字符?
  • 第一个问题没有空终止符。学习使用 _bstr_t 和 CComBSTR。 _bstr_t username(L"john"); HRESULT hr = pFoo->myDummyFunction(username);

标签: c++ com atl


【解决方案1】:

如果您正在调用的方法被声明为采用 BSTR 参数,那么您必须传递一个真正的 BSTR 作为参数。没有其他选择。

很抱歉,这不是您的偏好。我同意这不方便的原因有很多。然而,试图传递wchar_t* 而不是BSTR 就像试图将std::vector<wchar_t> 传递给需要std::wstring 的函数。希望你会同意,即使编译器没有阻止你,那也是无稽之谈。

BSTR 不仅仅是一个字符序列;它是一个可变大小的结构,具有非常明确的语义,恰好包含一个以 null 结尾的 wchar_t 序列作为它的主要成员。

让您感到困惑的是编译器似乎允许它们混合使用。这是因为 BSTR 的设计是为了在一些非常有限的情况下,可以使用 BSTR 对象,就像 it 只是一个 wchar_t*有时可以使用 BSTR 代替 wchar_t*,但反之则不行

这只是意味着 C++ 编译器无法区分 BSTR 和 wchar_t*。事实上,Windows 头文件本质上将 BSTR 定义为 typedef wchar_t* BSTR,因此它们对编译器来说是一样的,但编译器不知道 BSTR 结构的其余部分。这意味着编译器无法告诉您何时使用 BSTR 是合法的,何时使用 wchar_t* 是合法的:您有责任自己选择正确的。

About BSTR:

除了位于 BSTR 核心的以空字符结尾的字符序列之外,BSTR 还有一个大小前缀存储在第一个字符之前;并且 BSTR 必须分配在由 Windows 中的 COM 基础结构控制的特定堆中,这就是为什么它只能通过调用 SysAllocString() 和类似函数来创建。

在应该使用 BSTR 的地方使用 wchar_t* 会导致错误、崩溃和未定义的行为,具体取决于具体情况。我们不知道为什么会出现 E_OUTOFMEMORY 错误,但不难猜测:该函数可能会在尝试复制 BSTR 时尝试使用大小前缀。因为您传递的是 wchar_t* 而不是 BSTR,所以前缀中有垃圾,可能是一个荒谬的大数字,并且该函数尝试使用该大数字为副本分配大量内存,但失败了。


如果您想在自己的代码中使用 std::wstring 或 std::string,请继续。我会做同样的事情。但在调用该方法之前创建一个 BSTR,将其作为参数传递,然后释放 BSTR 并继续。

【讨论】:

    猜你喜欢
    • 2020-03-08
    • 2014-10-15
    • 2019-04-06
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-24
    • 2012-02-17
    相关资源
    最近更新 更多