Как правильно сбросить _bstr_t в `NULL`

В приведенном ниже фрагменте (упрощенный сценарий цикла)

_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

Что я ожидаю после another.Assign(NULL) является:

  • SysFreeString() НЕ называется
  • another установлен в NULL
  • ref-count уменьшается до 1
  • original имеет ref count=1 с существующими BSTR содержание.

Что случилось:

  • SysFreeString() призван к основному BSTR обоих another а также original
  • another установлен в NULL
  • пересчет original остается 2

another.Assign(NULL) кажется, чтобы освободить основной BSTR для обоих original а также another,
У нас был неожиданный сбой, потому что во время кодирования я думал _bstr_t::Assign() будет уменьшать количество ссылок вместо того, чтобы сразу же освободить BSTR,

Как правильно сбросить another в NULL без влияния original?

Пожалуйста, найдите ниже реализацию Assign от 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;
}
}

4

Решение

Реализация _bstr_t::Assign() был обновлен как упомянуто Игорь Тандетник в его комментарий.

Вот реализация в VS2010, и она работает как положено:

inline void _bstr_t::Assign(BSTR s)
{
_COM_ASSERT(s == NULL || m_Data == NULL || m_Data->GetWString() != s);

if (s == NULL || m_Data == NULL || m_Data->GetWString() != s)
{
_Free();

m_Data = new Data_t(s, TRUE);
if (m_Data == NULL) {
_com_issue_error(E_OUTOFMEMORY);
}
}
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector