Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;弱锁定()故障_C++_Qt_Weak References - Fatal编程技术网

C++ C++;弱锁定()故障

C++ C++;弱锁定()故障,c++,qt,weak-references,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 for

所以我有这个函数来添加监听器,它转换类的共享指针,这样我可以在收到通知后调用它

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;
void registerListener(std::shared_ptr listener)
{
如果(!侦听器){
qCWarning(观察者\记录器)锁(){
if(侦听器==共享){
返回;
}
iter++;
}否则{
iter=侦听器.擦除(iter);
}
}
自动弱=标准::弱\u ptr(侦听器);
听众:向后推(弱);
}
无效通知(std::函数onNotify)
{
//TODO生成一个foreach函数,该函数用于删除死掉的侦听器,以消除此代码重复
for(auto iter=listeners.begin();iter!=listeners.end();){
如果(自动共享=iter->lock()){
onNotify(共享);
iter++;
}否则{
iter=侦听器.擦除(iter);
}
}
}
私人:
向量侦听器;
由于某种原因,“iter->lock()”会出现故障。我会说这是一个Qt应用程序,但我故意没有创建任何线程(据我所知),所以我非常困惑我到底做错了什么来破坏这些弱线程。所以,如果我在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>) ()
#0 0x00007F856BD8BEC在标准中:_Sp_counted_base:_mu get_use_count()常量()
#标准中的1 0x00007f856bd844a8::_Sp_counted_base::_M_add_ref_lock_nothrow()()
#标准中的2 0x00007f856bd9cd7d::\uuuuu共享计数::\uuuuu共享计数(标准::\uuuu弱计数常数和,标准::无行计数)()
#标准中的3 0x00007f856bda9948::\uuuu共享\uu ptr::\uuuu共享\uu ptr(标准::\uuuu弱\uu ptr常量和,标准::无行)()
#4 0x00007f856bda8a62在标准::共享的ptr::共享的ptr(标准::弱的ptr常量和,标准::无行)
#std::weak_ptr::lock()常量()中的5 0x00007f856bda701a
#观察者::通知中的6 0x00007f856bda5624(标准::函数)()
#EntityObserver::notifyCreated(std::shared_ptr)()中的7 0x00007f856bda3a1a

编辑:迈克尔·伯尔(MichaelBurr)发布了一条消息,在添加新听众的同时,听众可能会注册,这完全有可能发生。这将导致迭代器无效,当我对不是弱\u ptr的内存段调用弱\u ptr.lock()时,砰的一声。我认为这里有一个寓意,我必须找到它。

我在你展示的代码中找不到明显的问题。所以我假设,问题在于您没有显示的代码。请记住,Q_对象修饰的对象也具有与qt相关的生命周期管理。也许有一些干扰

如果您将您的代码与我在这里发布的代码进行比较,并快速找到关键的差异,可能会有所帮助

#include <vector>
#include <algorithm>
#include <memory>

template <typename _Observable>
class IObserver
{
public:
    virtual ~IObserver() {}
    virtual void OnChange(const _Observable* what) = 0;
};

template <class T>
class CObservable
    : public IObserver<T> // Make sure this class breaks once IObserver<> changes.
{
public:
    typedef IObserver<T> Observer_t;
    typedef std::weak_ptr<Observer_t> Observer_reference;
    typedef std::shared_ptr<Observer_t> Observer_strong_reference;
    typedef T Class_t;
    typedef std::vector<Observer_reference> ObserverRefCollection;
private:

    ObserverRefCollection m_observers;

    void CleanupZombies()
    {
        m_observers.erase(std::remove_if(m_observers.begin(), m_observers.end(),
            [this](Observer_reference iter) -> bool
        {
            Observer_strong_reference o = iter.lock();
            return !o;
        }
        ), m_observers.end());
    }
public:
    void RegisterObserver(Observer_strong_reference& observer)
    {
        if (!observer)
            return;
        for (auto& iter : m_observers)
        {
            if (observer == iter.lock())
                return;
        }
        m_observers.push_back(Observer_reference(observer));
    }

    /*virtual*/ void OnChange(const Class_t* what)
    {
        bool hasZombies = false;
        for (auto& iter : m_observers)
        {
            Observer_strong_reference o = iter.lock();
            if (o)
            {
                o->OnChange(what);
            }
            else
            {
                hasZombies = true;
            }
        }
        if (hasZombies)
            CleanupZombies();
    }
};

class CObservableUint32
    : public CObservable<CObservableUint32>
{
    uint32_t m_value;
public:
    void Set(uint32_t newValue)
    {
        bool changed = newValue != m_value;
        m_value = newValue;
        if (changed)
        {
            OnChange(this);
        }
    }
    uint32_t Get() const
    {
        return m_value;
    }
};

class CSomeObserver
    : public IObserver < CObservableUint32 >
{

public:
    CSomeObserver()
        : IObserver<CObservableUint32>()
    {

    }
    virtual ~CSomeObserver()
    {

    }
    virtual void OnChange(const CObservableUint32* what)
    {

    }
};
#包括
#包括
#包括
模板
类IObserver
{
公众:
虚拟~IObserver(){}
虚空变化(常数可观测*什么)=0;
};
模板
类CObservable
:public IObserver//确保一旦IObserver发生更改,该类就会中断。
{
公众:
typedef IObserver Observer\u t;
typedef标准::弱ptr观察者参考;
typedef标准::共享的ptr观察者强参考;
类型定义T类;
typedef std::vector ObserverRefCollection;
私人:
ObserverRefCollection m_观察员;
void CleanupZombies()
{
m_observators.erase(std::remove_if(m_observators.begin(),m_observators.end(),
[这](观察家参考iter)->布尔
{
观察者强参考o=iter.lock();
回来!啊;
}
),m_.end());
}
公众:
无效注册表观察者(观察者\强\参考和观察者)
{
如果(!观察者)
返回;
用于(汽车和iter:m_观察员)
{
if(observer==iter.lock())
返回;
}
m_观测者。推回(观测者参考(观测者));
}
/*虚拟*/void OnChange(常量类\u t*what)
{
bool hasZombies=false;
用于(汽车和iter:m_观察员)
{
观察者强参考o=iter.lock();
如果(o)
{
o->OnChange(什么);
}
其他的
{
hasZombies=true;
}
}
如果(有僵尸)
清理僵尸();
}
};
类CObservableUint32
:公共服务
{
uint32μt mμ值;
公众:
无效集(uint32\u t newValue)
{
bool changed=newValue!=m_值;
m_值=新值;
如果(更改)
{
一旦改变(这个);
}
}
uint32\u t Get()常量
{
返回m_值;
}
};
CSOME类观察员
:public IObserver
{
公众:
CSomeObserver()
:IObserver()
{
}
虚拟~CSomeObserver()
{
}
虚拟void OnChange(const CObservableUint32*what)
{
}
};
在别的地方

    CObservableUint32 observable;
    {
        std::shared_ptr<IObserver<CObservableUint32> > observer = std::make_shared<CSomeObserver>();
        observable.RegisterObserver(observer);
        observable.Set(42UL);
    }
    observable.Set(100);
CObservableUint32可见;
{
std::shared_ptr observer=std::make_shared();
可观察的。注册观察者(观察者);
可观察。设置(42UL);
}
可观察。集(100);
调用
notify()
时,通过
onNotify()
函数对象调用的函数是否可能导致间接调用
registerListener()
(或可以在
侦听器
集合中添加或删除项的某些其他代码)

如果是,则在
notify()
for
循环中使用的
iter
可能无效。您可能希望将
notify()
更改为如下所示,它将所有
共享的\u ptr
对象排队等待通知,以便在任何
onNotify()
回调期间修改
侦听器
集合都无关紧要:

#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();
    }

}
#包括
无效通知(std::函数onNotify)
{
std::队列通知