_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