2008-10-05 85 views
8

当维护一个COM接口时,空BSTR的处理方式与NULL相同吗? 换句话说,这两个函数调用应该产生相同的结果吗?空的BSTR和NULL BSTR之间应该有区别吗?

// Empty BSTR 
CComBSTR empty(L""); // Or SysAllocString(L"") 
someObj->Foo(empty); 

// NULL BSTR 
someObj->Foo(NULL);  

回答

13

是 - 一个NULL BSTR与空白一样。我记得我们有从VS6切换到2003时发现的各种错误 - CComBSTR类改变了默认构造函数,它使用NULL而不是空字符串来分配它。例如,当您将BSTR视为常规C风格的字符串并将其传递给某个函数(如strlen)或尝试使用它初始化std::string时,会发生这种情况。

埃里克利珀讨论BSTR的很详细地Eric's Complete Guide To BSTR Semantics

让我首先列出的差异,然后 讨论 难以忍受的细节每一个点。

1)对于NULL和“”,BSTR必须具有相同的 语义。 PWSZ 通常对 这些语义有不同的语义。

2)BSTR必须分配并释放 与SysAlloc *系列的 功能。 PWSZ可以是 自动存储缓冲区,从 堆栈或分配malloc,新, LocalAlloc或任何其他内存 分配器。

3)BSTR的长度是固定的。 PWSZ 的长度可以是任意长度,仅限于 缓冲区中的有效内存量。

4)BSTR始终指向缓冲区中的第一个有效字符 。 PWSZ 可以是指向字符串缓冲器的中间或末尾 的指针。

5)当分配一个n字节的BSTR时, 有n/2个宽字符的空间。 当您为PWSZ 分配n个字节时,您可以存储n/2 - 1个字符 - 您必须为null留出空间。

6)BSTR可能包含任何包含零字符的Unicode数据 。 PWSZ 从不包含零字符 ,除了作为字符串结束标记。 BSTR和PWSZ在最后一个有效的 字符后始终有一个 零字符,但在BSTR中,有效的 字符可能为零字符。

7)一个BSTR实际上可能包含一个奇数的 字节数 - 它可能被用于移动二进制数据周围的 。一个PWSZ是 几乎总是偶数字节 和只用于存储Unicode 字符串。

+4

在抓握的手---我体验到MSXML代码不遵守NULL ==空规则,并展现出两种不同的行为。但那是5年前(MSXML 3,如果我没记错的话),希望他们现在已经解决了这个问题。 :-) – 2008-10-05 09:19:59

4

处理这种困境的最简单方法是使用CComBSTR并检查.Length()为零。这适用于空值和空值。

但是请记住,必须释放空的BSTR或存在内存泄漏。我最近在其他代码中看到了一些。很难找到,如果你不仔细看。