在维护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
用它初始化 a 时,就会发生这种情况。
Eric Lippert 在Eric 的 BSTR 语义完整指南中详细讨论了 BSTR :
让我先列出差异,然后详细讨论每一点。
BSTR 对于 NULL 和 "" 必须具有相同的语义。PWSZ 通常具有不同的语义。
必须使用 SysAlloc* 系列函数分配和释放 BSTR。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,否则会出现内存泄漏。我最近在其他人的代码中看到了其中的一些。如果你不仔细看的话,很难找到。