https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89303

--- Comment #13 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Alexandre Duret-Lutz from comment #6)
> I mentioned in my first comment that I had also cases that threw
> bad_weak_ptr.
> I've been able to reproduce those as follows:
> 
> % cat badwptr.cc
> #include <memory>
> 
> class blob final: public std::enable_shared_from_this<blob>
> {
> };
> 
> int main()
> {
>   std::shared_ptr<blob> tg = std::make_shared<blob>();
>   return tg->shared_from_this().use_count();

At this line GDB shows that tg._M_ptr->_M_weak_this._M_refcount is not set
correctly:

(gdb) p *tg._M_ptr
$6 = {<std::__enable_shared_from_this<blob, 0>> = {_M_weak_this = {_M_ptr =
0x614e80, _M_refcount = {_M_pi = 0x0}}}, data = 0x614ea0}
(gdb) p tg 
$7 = {_M_ptr = 0x614e80, _M_refcount = {_M_pi = 0x614e70}}

The _M_weak_this._M_refcount._M_pi member should be the same pointer as
tg._M_refcount._M_pi.

This suggests that __weak_count::_M_assign didn't work properly, and that could
also explain why the weak count isn't correctly decremented in the other test
case, if _M_pi is null here:

      ~__weak_count() noexcept
      {
        if (_M_pi != nullptr)
        {
          _M_pi->_M_weak_release();
        }
#ifdef FIXME
        else __builtin_puts("null");
#endif
      }

That would explain why _M_weak_release() isn't called.

So if the two bugs have the same root cause, it seems to be a problem in
__weak_count::_M_assign, failing to set _M_pi here:

      __weak_count&
      operator=(const __shared_count<_Lp>& __r) noexcept
      {
        _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
        if (__tmp != nullptr)
          __tmp->_M_weak_add_ref();
        if (_M_pi != nullptr)
          _M_pi->_M_weak_release();
        _M_pi = __tmp;
        return *this;
      }





> }
> 
> % g++ -g -O badwptr.cc
> % ./a.out
> terminate called after throwing an instance of 'std::bad_weak_ptr'
>   what():  bad_weak_ptr
> 
> When compiled with -O2 or -O0, the program exits with $?=2 as expected.

Reply via email to