【发布时间】:2010-09-15 08:36:17
【问题描述】:
在维护COM 接口时,空的BSTR 是否应该以与NULL 相同的方式处理?
换句话说,这两个函数调用应该产生相同的结果吗?
// Empty BSTR
CComBSTR empty(L""); // Or SysAllocString(L"")
someObj->Foo(empty);
// NULL BSTR
someObj->Foo(NULL);
【问题讨论】:
在维护COM 接口时,空的BSTR 是否应该以与NULL 相同的方式处理?
换句话说,这两个函数调用应该产生相同的结果吗?
// Empty BSTR
CComBSTR empty(L""); // Or SysAllocString(L"")
someObj->Foo(empty);
// NULL BSTR
someObj->Foo(NULL);
【问题讨论】:
是的 - NULL BSTR 与空 BSTR 相同。我记得当我们从 VS6 切换到 2003 时,我们发现了各种各样的错误 - CComBSTR 类对使用 NULL 而不是空字符串分配它的默认构造函数进行了更改。例如,当您将 BSTR 视为常规 C 样式字符串并将其传递给诸如 strlen 之类的函数,或尝试使用它初始化 std::string 时,就会发生这种情况。
Eric Lippert 在Eric's Complete Guide To BSTR Semantics 中详细讨论了 BSTR:
让我先列出差异,然后 然后讨论中的每一点 令人痛苦的细节。
BSTR 必须具有相同的 NULL 和 "" 的语义。一个 PWSZ 经常有不同的语义 那些。
必须分配和释放 BSTR 与 SysAlloc* 系列 职能。 PWSZ 可以是 从自动存储缓冲区 堆栈或使用 malloc、new、 LocalAlloc 或任何其他内存 分配器。
BSTR 是固定长度的。一个 PWSZ 可以是任意长度,仅受以下限制 它的有效内存量 缓冲区。
BSTR 总是指向第一个 缓冲区中的有效字符。一个 PWSZ 可能是指向中间或结尾的指针 字符串缓冲区。
在分配 n 字节 BSTR 时,您 有空间容纳 n/2 个宽字符。 当您为 PWSZ 分配 n 个字节时 您可以存储 n / 2 - 1 个字符 -- 你必须为空值留出空间。
BSTR 可以包含任何 Unicode 数据 包括零字符。一个 PWSZ 从不包含零字符 除了作为字符串结束标记。 BSTR 和 PWSZ 总是有一个 最后一个有效字符后的零字符 字符,但在 BSTR 中是有效的 字符可能是零字符。
BSTR 实际上可能包含一个奇数 字节数——它可以用于 移动二进制数据。 PWSZ 是 几乎总是偶数字节 并且仅用于存储 Unicode 字符串。
【讨论】:
处理这种困境的最简单方法是使用 CComBSTR 并检查 .Length() 是否为零。这适用于空值和 NULL 值。
但是,请记住,必须释放空的 BSTR,否则会出现内存泄漏。我最近在其他人的代码中看到了其中的一些。如果不仔细看的话,很难找到。
【讨论】: