Question

What is the correct way of doing this:

_bstr_t description;
errorInfo->GetDescription( &description.GetBSTR() );

or:

_bstr_t description;
errorInfo->GetDescription( description.GetAddress() );

Where IError:GetDescription is defined as:

HRESULT GetDescription (BSTR *pbstrDescription);

I know I could easily do this:

BSTR description= SysAllocString (L"Whateva"));
errorInfo->GetDescription (&description);
SysFreeString (description);

Thanks

Was it helpful?

Solution

The BSTR is reference counted, I seriously doubt that will work right if you use GetAddress(). Sadly the source code isn't available to double-check that. I've always done it like this:

BSTR temp = 0;
HRESULT hr = p->GetDescription(&temp);
if (SUCCEEDED(hr)) {
    _bstr_t wrap(temp, FALSE);
    // etc..
}

OTHER TIPS

To follow up on @Hans's answer - the appropriate way to construct the _bstr_t depends on whether GetDescription returns you a BSTR that you own, or one that references memory you don't have to free.

The goal here is to minimize the number of copies, but also avoid any manual calls to SysFreeString on the returned data. I would modify the code as shown to clarify this:

BSTR temp = 0;
HRESULT hr = p->GetDescription(&temp);
if (SUCCEEDED(hr)) {
    _bstr_t wrap(temp, false);    // do not copy returned BSTR, which
                                  // will be freed when wrap goes out of scope.
                                  // Use true if you want a copy.
    // etc..
}

A late answer that may not apply to earlier (or later) versions of Visual Studio; however, VS 12.0 has the _bstr_t implementation inline, and evidently an internal Data_t instance is created with a m_RefCount of 1 when calling GetBSTR() on a virgin _bstr_t. So the _bstr_t lifecycle in your first example looks to be okay:

_bstr_t description;
errorInfo->GetDescription( &description.GetBSTR() );

But if _bstr_t is dirty, the existing internal m_wstr pointer will be overwritten, leaking the previous memory it referenced.

By using the following operator&, a dirty _bstr_t can be used given that it's first cleared via Assign(nullptr). The overload also provides the convenience of utilizing the address operator instead of GetBSTR();

BSTR *operator&(_bstr_t &b) {
    b.Assign(nullptr);
    return &b.GetBSTR();
}

So, your first example could instead look like the following:

_bstr_t description(L"naughty");
errorInfo->GetDescription(&description);

This evaluation was based on comutil.h from VS 12.0.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top