インターフェイスを維持する場合COM
、空は?BSTR
と同じように扱う必要があります。NULL
言い換えれば、これらの2つの関数呼び出しは同じ結果を生成する必要がありますか?
// Empty BSTR
CComBSTR empty(L""); // Or SysAllocString(L"")
someObj->Foo(empty);
// NULL BSTR
someObj->Foo(NULL);
はい-NULLBSTRは空のBSTRと同じです。VS6から2003に切り替えたときに発見されたあらゆる種類のバグがあったことを覚えています。CComBSTRクラスは、空の文字列ではなくNULLを使用して割り当てるデフォルトのコンストラクターに変更されました。これは、たとえばBSTRを通常のCスタイルの文字列として扱い、それをのような関数に渡すか、それを使用strlen
して初期化しようとした場合に発生std::string
します。
Eric Lippertは、EricのBSTRセマンティクスの完全ガイドでBSTRについて詳しく説明しています。
最初に違いをリストし、次に各ポイントについて非常に詳細に説明します。
BSTRは、NULLと""に対して同一のセマンティクスを持っている必要があります。PWSZは、それらに対して異なるセマンティクスを持っていることがよくあります。
BSTRは、SysAlloc*ファミリーの関数で割り当ておよび解放する必要があります。PWSZは、スタックからの自動ストレージバッファーにすることも、malloc、new、LocalAlloc、またはその他のメモリアロケータで割り当てることもできます。
BSTRは固定長です。PWSZの長さは任意で、バッファ内の有効なメモリの量によってのみ制限されます。
BSTRは、常にバッファ内の最初の有効な文字を指します。PWSZは、文字列バッファの中央または最後へのポインタである可能性があります。
nバイトのBSTRを割り当てる場合、n/2ワイド文字用のスペースがあります。PWSZにnバイトを割り当てると、n/2-1文字を格納できます。nullの余地を残す必要があります。
BSTRには、ゼロ文字を含む任意のUnicodeデータを含めることができます。PWSZには、文字列の終わりマーカーを除いて、ゼロ文字が含まれることはありません。BSTRとPWSZはどちらも、最後の有効な文字の後に常にゼロ文字がありますが、BSTRでは、有効な文字がゼロ文字である場合があります。
BSTRには、実際には奇数のバイトが含まれている場合があります。これは、バイナリデータを移動するために使用される場合があります。PWSZはほとんどの場合偶数バイトであり、Unicode文字列を格納するためにのみ使用されます。
このジレンマを処理する最も簡単な方法は、CComBSTRを使用して、.Length()がゼロであることを確認することです。これは、空の値とNULL値の両方で機能します。
ただし、空のBSTRを解放する必要があります。そうしないと、メモリリークが発生します。私は最近他のコードでそれらのいくつかを見ました。注意深く見ていなければ、見つけるのはかなり難しいです。