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