views:

32

answers:

1

I found some objects in my C++ program can't be released due to the Signal2 of boost won't release those arguments in object created by boost::bind. Here is the code to reproduce the problem:

#include <iostream>
#include <string>

#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include <boost/shared_ptr.hpp>

using namespace std;
using namespace boost;

class Foo {
public:
    Foo() {
        cout << "Foo is created." << endl;
    }
    ~Foo() {
        cout << "Foo is deleted." << endl;
    }
};

typedef shared_ptr<Foo> FooPtr;
typedef signals2::signal<void ()> Signal;

void bar1(FooPtr pFoo) {

}

void bar2(Signal &s) {
    FooPtr pFoo(new Foo());
    s.connect(bind(bar1, pFoo));
}

int main() {
    Signal signal;
    bar2(signal);
    cout << "A" << endl;
    signal.disconnect_all_slots();
    cout << "B" << endl;
    return 0;
}

And the output looks like this

Foo is created.
A
B
Foo is deleted.

I thought the signal.disconnect_all_slots would delete all connections. But actually, it didn't. I just read the source code of signals2, it seems that the signal.disconnect only set a flag "disconnect" in those connection, it never delete those object. Why the signal won't delete those disconnected connections? Isn't it a very strange behavior? What is the reason of keep those connections rather than delete them? And how to force it to remove those connections?

A: 

Ensuring release of connections appears to be idiosyncratic per the info here - this is for signals, but the issue remains in signals2.

In your case, the modified version below does what you want, I think:

#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include <boost/scoped_ptr.hpp>

using namespace std;
using namespace boost;

class Foo {
public:
    Foo() {
        cout << "Foo is created." << endl;
    }

    void bar()
    {
    }

    ~Foo() {
        cout << "Foo is deleted." << endl;
    }
};

typedef signals2::signal<void ()> Signal;

int main() {
    Signal signal;
    {
        scoped_ptr<Foo> foo(new Foo);
        signals2::scoped_connection c = 
            signal.connect(boost::bind(&Foo::bar, foo.get()));

        cout << "C " << signal.num_slots() << endl;
        signal.disconnect_all_slots();

        cout << "D " << signal.num_slots() << endl;
    }
    cout << "E " << signal.num_slots() << endl;
    return 0;
}

Output:

Foo is created.
C 1
D 0
Foo is deleted.
E 0
Steve Townsend