So, I have this function to add listeners, and it converts the general class pointers, so I can call later when I get a notification.
void registerListener(std::shared_ptr<T> listener) { if (!listener) { qCWarning(OBSERVER_LOGGER) << "Attempted to register a null observer."; return; } // TODO make a foreach function that removes dead listeners to get rid of this code dupe for (auto iter=listeners.begin(); iter != listeners.end(); ) { if (auto shared = iter->lock()) { if (listener == shared) { return; } iter++; } else { iter = listeners.erase(iter); } } auto weak = std::weak_ptr<T>(listener); listeners.push_back(weak); } void notify(std::function<void(std::shared_ptr<T>)> onNotify) { // TODO make a foreach function that removes dead listeners to get rid of this code dupe for (auto iter=listeners.begin(); iter != listeners.end(); ) { if (auto shared = iter->lock()) { onNotify(shared); iter++; } else { iter = listeners.erase(iter); } } } private: std::vector<std::weak_ptr<T>> listeners;
and for some reason "iter-> lock ()" segfaults. I will say that this is a Qt application, but I intentionally did not create ANY threads (that I know), so I am just confused by what I am doing wrong so that these weak fragments break. Therefore, if I run it in gdb, it works fine. But if I set "set disable-randomization off", then I get an error. Therefore, I feel that this is some kind of strange problem when with uninitialized variables. If this helps, this is the stack when I crashed into gdb.
#0 0x00007f856bd8beec in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_get_use_count() const () #1 0x00007f856bd844a8 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_add_ref_lock_nothrow() () #2 0x00007f856bd9cd7d in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count(std::__weak_count<(__gnu_cxx::_Lock_policy)2> const&, std::nothrow_t) () #3 0x00007f856bda9948 in std::__shared_ptr<IEntityListener<Assignment>, (__gnu_cxx::_Lock_policy)2>::__shared_ptr(std::__weak_ptr<IEntityListener<Assignment>, (__gnu_cxx::_Lock_policy)2> const&, std::nothrow_t) () #4 0x00007f856bda8a62 in std::shared_ptr<IEntityListener<Assignment> >::shared_ptr(std::weak_ptr<IEntityListener<Assignment> > const&, std::nothrow_t) () #5 0x00007f856bda701a in std::weak_ptr<IEntityListener<Assignment> >::lock() const () #6 0x00007f856bda5624 in Observer<IEntityListener<Assignment> >::notify(std::function<void (std::shared_ptr<IEntityListener<Assignment> >)>) () #7 0x00007f856bda3a1a in EntityObserver<Assignment>::notifyCreated(std::shared_ptr<Assignment>) ()
EDIT: Michael Burr posted an opportunity to listen to listeners, while new listeners added what could happen completely. This will cause the iterator to be invalid, and when I go to the weak_ptr.lock () call in the memory section, which is not weak_ptr, BOOM. I think that there is morality, somewhere I just have to find it.
source share