Programming with CComBSTR
The ATL class CComBSTR provides a wrapper around the BSTR data type. While CComBSTR is a useful tool, there are several situations that require caution.
Although several CComBSTR methods will automatically convert an ANSI string argument into Unicode, the methods will always return Unicode format strings. To convert the output string back to ANSI, use an ATL conversion class. For more information on the ATL conversion classes, see ATL and MFC String Conversion Macros.
// Declare a CComBSTR object. Although the argument is ANSI, // the constructor converts it into UNICODE. CComBSTR bstrMyString("Hello World"); // Convert the string into an ANSI string CW2A szMyString(bstrMyString); // Display the ANSI string MessageBoxA(NULL, szMyString, "String Test", MB_OK);
If you are using a string literal to modify a CComBSTR object, use wide character strings. This will reduce unnecessary conversions.
As with any well-behaved class, CComBSTR will free its resources when it goes out of scope. If a function returns a pointer to the CComBSTR string, this can cause problems, as the pointer will reference memory that has already been freed. In these cases, use the Copy method, as shown below.
// The wrong way to do it BSTR * MyBadFunction() { // Create the CComBSTR object CComBSTR bstrString(L"Hello World"); // Convert the string to uppercase HRESULT hr; hr = bstrString.ToUpper(); // Return a pointer to the BSTR. ** Bad thing to do ** return &bstrString; } // The correct way to do it HRESULT MyGoodFunction(/*[out]*/ BSTR* bstrStringPtr) { // Create the CComBSTR object CComBSTR bstrString(L"Hello World"); // Convert the string to uppercase HRESULT hr; hr = bstrString.ToUpper(); if (hr != S_OK) return hr; // Return a copy of the string. return bstrString.CopyTo(bstrStringPtr); }
Passing the address of an initialized CComBSTR to a function as an [out] parameter causes a memory leak.
In the example below, the string allocated to hold the string "Initialized" is leaked when the function MyGoodFunction replaces the string.
CComBSTR bstrLeak(L"Initialized");
HRESULT hr = MyGoodFunction(&bstrLeak);
To avoid the leak, call the Empty method on existing CComBSTR objects before passing the address as an [out] parameter.
Note that the same code would not cause a leak if the function's parameter was [in, out].