Also habe ich diese Funktion, um Listener hinzuzufügen und es konvertiert gemeinsame Zeiger einer Klasse, so dass ich es später aufrufen kann, wenn ich eine Benachrichtigung bekomme.C++ weak_ptr.lock() segfault
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;
und aus irgendeinem Grund "ITER> lock()" segfaults. Ich werde sagen, dass dies eine Qt-Anwendung ist, aber ich habe absichtlich KEINE Threads erstellt (von denen ich weiß), so dass ich nur sehr verwirrt bin, was ich falsch mache, um diese weak_ptrs zu brechen. Also, wenn ich es in gdb laufen lasse, funktioniert es gut. Aber wenn ich setze, "disable-randomization off" dann bekomme ich den Fehler. Ich denke, das ist ein seltsames Problem mit nicht initialisierten Variablen. Wenn es hilft, ist das der Stack wenn ich in gdb stürze.
#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 geschrieben, die Möglichkeit der Zuhörer während neue Hörer sich eintragen, wo hinzugefügt wird, die völlig passieren könnte. Dies würde dazu führen, dass der Iterator ungültig ist, und wenn ich gehe, um weak_ptr.lock() für einen Speicherabschnitt aufzurufen, der kein weak_ptr ist, BOOM. Ich denke, hier ist eine Moral, irgendwo muss ich sie finden.
Können Sie uns ein komplettes minimales Arbeitsprogramm mit einem main()? –
Sie könnten 'auto weak = std :: weak_ptr (Listener);' zu 'std :: weak_ptr weak (Listener);'. Außerdem ist es * sehr * verwirrend, wie Sie eine Funktion namens 'notify()' haben, die ein Argument mit dem gleichen Namen verwendet - was auch eine Funktion ist! –
Ich kann versuchen, später habe ich eigentlich kein einfacheres Programm, das noch stürzt. Das Ding, das keinen Sinn macht, ist, dass das für die letzten 6 Monate funktionierte, und dann habe ich einen neuen Hörer und BOOM hinzugefügt, plötzlich explodiert alles. Aber ich ging sogar so weit, den neuen Zuhörer zu differieren, und das ist GENAU DAS GLEICHE! – Buttink