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.