Почему эта реализация COM IUnknown :: Release работает? - PullRequest
6 голосов
/ 01 февраля 2011

Из примеров, которые я видел, COM IUnknown::Release() реализация функции выглядит примерно так:

ULONG Release()
{
    InterlockedDecrement(&m_count);
    if(m_count == 0) {
       delete this;
    }
    return m_count;
}

Итак, если m_count равен 0, мы удаляем объект this и возвращаем счетчик ссылок. Чего я не понимаю, так это почему?!?!

  1. Удаление объекта не разрушит стек вызовов или это нормально, поскольку он удерживается потоком, поэтому он не имеет ничего общего с объектом ???

  2. Если объект был удален, как это возможно, что мы можем вернуть m_count, он должен был быть удален. Я мог бы убедить себя, что все в порядке, если после удаления код вернет жестко закодированный 0, но как получится, что он может вернуть член?!?!

Большое спасибо за вашу помощь! : -)

Ответы [ 2 ]

15 голосов
/ 01 февраля 2011

Этот код является поддельным. Никогда нельзя доверять m_count после декремента. Правильный код: всегда , например:

ULONG Release()
{
     ULONG count = InterlockedDecrement(&m_count);
     if(count == 0){ delete this; }
     return count;
}
1 голос
/ 02 февраля 2011

То, что вы наблюдаете, является неопределенным поведением.Стек вызовов не изменяется на delete this; и delete this сам по себе всегда безопасен , но делает this указатель недействительным , что означает, что вы больше не можете разыменовывать его.

Есть два возможных объяснения того, что вы наблюдаете.Либо рассматриваемая реализация просто не разыменовывает указатель this для получения m_count при возврате из функции - она ​​загружается в регистр и просто использует это значение, поэтому this не разыменовывается, и вы не делаетенаблюдайте за любой проблемой или когда delete завершает работу, память, занятая объектом, все еще отображается в адресное пространство процесса и остается технически доступной, поэтому разыменование this завершается успешно и m_count успешно читается.Я полагаю, что последнее более вероятно.

Каким бы ни было объяснение этого неопределенного поведения, вы не можете на это полагаться, используйте то, что пользователь Remus Rusanu предлагает в своем ответе .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...