In the snippet below (simplified loop script)
_bstr_t original(OLESTR("MyString")); // ref-count = 1 _bstr_t another; another = original; // ref-count = 2 // do something with another another.Assign(NULL); // expected: ref-count = 1, and another = NULL // reset another to NULL before doing other operations
What I expect after another.Assign(NULL) :
SysFreeString() NOT calledanother set to NULL- ref-count decreases to 1
original has ref count=1 with existing BSTR content.
What happened:
SysFreeString() is called for the base BSTR both another and originalanother set to NULL- ref-count
original remains 2
another.Assign(NULL) seems to free the base BSTR for original and another .
We had an unexpected failure, because during the encoding, I thought that _bstr_t::Assign() would decrease the reference count instead of freeing up the BSTR right away.
How to properly reset another to NULL not affect original ?
The following is a description of Assign from VC++ 6 .
// assignment operator copies internal data and increases reference count inline _bstr_t& _bstr_t::operator=(const _bstr_t& s) throw() { const_cast<_bstr_t*>(&s)->_AddRef(); _Free(); m_Data = s.m_Data; return *this; } // but _bstr_t::Assign() calls _bstr_t::Data_t::Assign() // without touching ref count inline void _bstr_t::Assign(BSTR s) throw(_com_error) { if (m_Data != NULL) { m_Data->Assign(s); } else { m_Data = new Data_t(s, TRUE); if (m_Data == NULL) { _com_issue_error(E_OUTOFMEMORY); } } } // it calls _bstr_t::Data_t::_Free() instead of _bstr_t::_Free() ! inline void _bstr_t::Data_t::Assign(BSTR s) throw(_com_error) { _Free(); if (s != NULL) { m_wstr = ::SysAllocStringByteLen(reinterpret_cast<char*>(s), ::SysStringByteLen(s)); } } // this _Free() straight away deallocates the BSTR! inline void _bstr_t::Data_t::_Free() throw() { if (m_wstr != NULL) { ::SysFreeString(m_wstr); } if (m_str != NULL) { delete [] m_str; } } // properly decrements ref count inline void _bstr_t::_Free() throw() { if (m_Data != NULL) { m_Data->Release(); m_Data = NULL; } }
source share