当通知符/信号超出范围时,在boost bind中释放回调侦听器对象

时间:2012-04-11 20:21:20

标签: c++ visual-c++ boost memory-leaks boost-signals

在某种情况下,只能在向量中保存指针,以便我可以使用它们释放dtor中的内存。

我有一个对象从增强信号中侦听回调(插槽)。这些对象需要的范围大于创建它的方法,因为它应该比发生它的时候更多地监听发出的增强信号那么,我必须在堆中分配内存并立即使用该实例订阅增强信号。

现在,当持有信号的类被销毁时,这些对象应该从内存中释放出来。现在有什么选择,

  • 当boost信号超出范围并且所有侦听boost:bind对象都被破坏时,boost是否释放所有这些对象?

  • 共享指针或智能指针会帮助我吗?

  • 我是否必须在信令服务中使用所有这些指针的向量来在其析构函数中释放?有更好的方法吗?

    void methodA(){
    
    CallbackHandler* cbHandler=new CallbackHandler(..);    //Allocating in heap as we want to receive boost signals on  
                                                           //this instance even after this method exits
    signalingService.subscribeToCertainSignals(signalType,boost::bind(&CallbackHandler::boostSlotListener,cbHandler,_1));
    }
    
    
    // Boost Signal -SignalingService
     boost::signal<void (const std::string &msg)> signal1;
     boost::signal<void (const std::string &msg)> signal2;
    
     void subscribeToCertainSignals(const std::string& signalType,boost::function<void (const std::string& str)> bindObject){
            this->signal1.connect(bindObject);
            this->signal2.connect(bindObject);
    
     }
     void sendSignals(A a){
         if(check){
            this->signal1("somestring1");
          }else{
            this->signal1("somestring1");
          }
    

    };

2 个答案:

答案 0 :(得分:1)

你可以这样做的一种方法是将shared_ptr存储到持有信号的对象中的所有侦听器,并将weak_ptr存储到外部的侦听器。当破坏保存信号的对象时,每个shared_ptr中的引用计数将转到0,并且将删除指向的侦听器。现在,当您下次尝试锁定weak_ptr以从持有信号的对象外部访问侦听器时,锁定将失败,因为将删除指针 - 这很容易被检测到,因为lock将返回null shared_ptr

这是一个具体的例子(不幸的是,不是使用Boost.Signals,只是为了说明这一点):

#include <iostream>
#include <memory>
#include <vector>

class Listener
{
public:
    virtual ~Listener() {}
    virtual void signal() = 0;
};

class Subject
{
private:
    std::vector<std::shared_ptr<Listener> > m_listeners;
public:
    void add_listener(const std::shared_ptr<Listener>& listener)
    {
        m_listeners.push_back(listener);
    }

    void signal_all()
    {
        // Note that you could use "auto it = ..." here in C++11.
        for(std::vector<std::shared_ptr<Listener> >::iterator it=m_listeners.begin(), iend=m_listeners.end(); it!=iend; ++it)
        {
            (*it)->signal();
        }
    }
};

class MyListener : public Listener
{
    void signal()
    {
        std::cout << "Signalled!\n";
    }
};

int main()
{
    std::vector<std::weak_ptr<Listener> > listeners;

    {
        Subject s;  

        std::shared_ptr<Listener> listener(new MyListener);
        s.add_listener(listener);
        listeners.push_back(listener);
        listener.reset();

        s.signal_all();

        // Locking the listener yields the listener here.
        std::cout << listeners[0].lock() << '\n';
    }

    // Locking the listener now yields null because s no longer exists.
    std::cout << listeners[0].lock() << '\n';

    return 0;
}

输出:

Signalled!
<some valid non-null address>
00000000

答案 1 :(得分:0)

我认为最好使用boost scoped_connection。此对象专为您要查找的内容而设计。

例如,您可以在列表中存储范围内的连接,当列表的所有者死亡时,列表将调用范围连接的析构函数,并且会自动断开对象与信号槽的连接。

在此处阅读详细信息:

http://www.boost.org/doc/libs/1_46_1/doc/html/boost/signals2/scoped_connection.html