_bstr_t objects

A _bstr_t object encapsulates the BSTR data type. The class manages resource allocation and de-allocation through function calls to SysAllocString and SysFreeString.

It isn’t necessary to de-allocate or free a string by calling SysFreeString that has been allocated by _bstr_t. Doing this might lead to double free of the allocated string when the _bstr_t class is destructed. This could lead
to access violation.

_bstr_t is defined in comutil.h as follows:

 

class _bstr_t {

public:

    // Constructors

    //

    _bstr_t() throw();

    _bstr_t(const _bstr_t& s) throw();

    _bstr_t(const char* s) ;

    _bstr_t(const wchar_t* s) ;

    _bstr_t(const _variant_t& var) ;

    _bstr_t(BSTR bstr, bool fCopy) ;

 

    // Destructor

    //

    ~_bstr_t() throw();

 

    // Assignment operators

    //

    _bstr_t& operator=(const _bstr_t& s) throw();

    _bstr_t& operator=(const char* s);

    _bstr_t& operator=(const wchar_t* s);

    _bstr_t& operator=(const _variant_t& var);

 

    // Operators

    //

    _bstr_t& operator+=(const _bstr_t& s);

    _bstr_t operator+(const _bstr_t& s) const;

     // Friend operators

    //

    friend _bstr_t operator+(const char* s1, const _bstr_t& s2);

    friend _bstr_t operator+(const wchar_t* s1, const _bstr_t& s2);

 

    // Extractors

    operator const wchar_t*() const throw();

    operator wchar_t*() const throw();

    operator const char*() const ;

    operator char*() const ;

 

    // Comparison operators

    //

    bool operator!() const throw();

    bool operator==(const _bstr_t& str) const throw();

    bool operator!=(const _bstr_t& str) const throw();

    bool operator<(const _bstr_t& str) const throw();

    bool operator>(const _bstr_t& str) const throw();

    bool operator<=(const _bstr_t& str) const throw();

    bool operator>=(const _bstr_t& str) const throw();

 

    // Low-level helper functions

    //

    BSTR copy(bool fCopy = true) const;

    unsigned int length() const throw();

     // Binary string assign

    //

    void Assign(BSTR s);

     // Get the physical BSTR

    //

    BSTR& GetBSTR();

    BSTR* GetAddress();

 

    // Attach to the internal BSTR w/o copying

    //

    void Attach(BSTR s) ;

 

    // Detach the internal BSTR

    //

    BSTR Detach() throw();

 

private:

    // Referenced counted wrapper

    //

    class  Data_t {

    public:

         // Constructors

        //

        Data_t(const char* s);

        Data_t(const wchar_t* s);

        Data_t(BSTR bstr, bool fCopy);

        Data_t(const _bstr_t& s1, const _bstr_t& s2) ;

 

        // Reference counting routines

        //

        unsigned long AddRef() throw();

        unsigned long Release() throw();

        unsigned long RefCount() const throw();

         // Extractors

        //

        operator const wchar_t*() const throw();

        operator const char*() const ;

         // Low-level helper functions

        //

        const wchar_t* GetWString() const throw();

        wchar_t*& GetWString() throw();

        const char* GetString() const;

         BSTR Copy() const;

        void Assign(BSTR s) ;

        void Attach(BSTR s) throw();

        unsigned int Length() const throw();

        int Compare(const Data_t& str) const throw();

 

        //  Exception agnostic wrapper for new

        //

        void*  operator new(size_t sz);         

 

    private:

        BSTR m_wstr;

        mutable char* m_str;

        unsigned long m_RefCount;

 

        // Never allow default construction

        //

        Data_t() throw();

 

        // Never allow copy

        //

        Data_t(const Data_t& s) throw();

 

        // Prevent deletes from outside. Release() must be used.

        //

        ~Data_t() throw();

         void _Free() throw();

    };

 

private:

    // Reference counted representation

    //

    Data_t* m_Data;

 

private:

    // Low-level utilities

    //

    void _AddRef() throw();

    void _Free() throw();

    int _Compare(const _bstr_t& str) const throw();

};

 

The destructor does a free as follows:

 

// Destructor

//

inline _bstr_t::~_bstr_t() throw()

{

    _Free();

}

 

// Free the BSTR

//

inline void _bstr_t::_Free() throw()

{

    if(m_Data != NULL) {

        m_Data->Release();

        m_Data = NULL;

    }

}

  

m_Data is a member of the Data_t class. m_Data->Release() decrements the reference count of the object and deletes the object, which actually calls Data_t::_Free() to free the string by calling SysFreeString() .
Please see the code for Data_t::_Free() below.

 

inline void _bstr_t::Data_t::_Free() throw()

{

   if (m_wstr != NULL)

   {

       ::SysFreeString(m_wstr);

   }

   if (m_str != NULL)

  {

      delete [] m_str;

  }

}

 

Here are the Data_t functions that allocate the BSTR.

 

// Construct a Data_t from a const char*

//

inline _bstr_t::Data_t::Data_t(const  char* s)

    : m_str(NULL), m_RefCount(1)

{

    m_wstr = _com_util::ConvertStringToBSTR(s);

}

 

// Construct a Data_t from a const wchar_t*

//

inline _bstr_t::Data_t::Data_t(const  wchar_t* s)

    : m_str(NULL), m_RefCount(1)

{

    m_wstr = ::SysAllocString(s);

 

    if (m_wstr == NULL && s != NULL) {

        _com_issue_error(E_OUTOFMEMORY);

    }

}

 

Reference: msdn.microsoft.com/en-us/library/zthfhkd6(v=vs.80).ASPX