But*_*ink 5 c++ qt weak-references
所以我有这个函数来添加监听器,它转换一个类的共享指针,以便我可以在收到通知后稍后调用它.
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;
Run Code Online (Sandbox Code Playgroud)
由于某种原因,"iter-> lock()"段错误.我会说这是一个Qt应用程序,但我故意没有创建任何线程(我知道)所以我只是非常困惑我做错了让这些weak_ptrs中断.所以,如果我在gdb中运行它,它的工作正常.但如果我设置,"设置禁用随机化关闭"然后我得到错误.因此,对于未初始化的变量,我觉得这是一个奇怪的问题.如果它有帮助,这是我在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>) ()
Run Code Online (Sandbox Code Playgroud)
编辑:迈克尔伯尔发布了听众登记的可能性,而新的听众正在被添加,这可能完全发生.这会导致迭代器无效,并且当我在不是weak_ptr,BOOM的内存部分上调用weak_ptr.lock()时.我认为这里有道德,我必须找到它.
当notify()调用时,通过函数对象调用的函数是否可能onNotify()会导致registerListener()被间接调用(或可以添加或删除集合中的条目的其他代码listeners)?
如果是这样,则循环iter中使用的notify() for可以无效。您可能希望更改notify()为如下所示,它将所有要通知的对象排队,以便在任何回调期间修改集合都shared_ptr无关紧要:listenersonNotify()
#include <queue>
void notify(std::function<void(std::shared_ptr<T>)> onNotify)
{
std::queue<std::shared_ptr<T>> notify_targets;
for (auto iter=listeners.begin(); iter != listeners.end(); ) {
if (auto shared = iter->lock()) {
notify_targets.push(shared);
iter++;
} else {
iter = listeners.erase(iter);
}
}
while (!notify_targets.empty()) {
onNotify(notify_targets.front());
notify_targets.pop();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1076 次 |
| 最近记录: |