0

By far I've encountered the same problem. The document in boost web says that the disconnection occurs when 'An object tracked by the slot is destroyed.', however, I tested it doesn't work in that way. So I prefer to disconnect manually although it's little bit troublesome.

My test code :

class MySignal {
public:
    boost::signals2::signal<void ()> signal_one;
    boost::signals2::signal<void ()> signal_two;

};

class MySlot {
public:
    void SlotOne() {
        std::cout << "slot_one" << std::endl;
    }
    void SlotTwo() {
        std::cout << "slot_two" << std::endl;
    }
};

int main() {

    MySignal signal;
    auto* slot = new MySlot;

    auto c = connect(signal.signal_one, slot, &MySlot::SlotOne);
//    c.disconnect();

    if (slot != nullptr) {
        delete slot;
        slot = nullptr;
    }

    signal.signal_one();

    return 0;
}

Can anybody tell me why the slot can still be triggered while I already destroyed the slot object?

I can only convince myself that the boost's document says the 'disconnection' can occur under some circumstances but doesn't say it will happen automatically.

Words below are what the boost document says:
Signal/slot disconnections occur when any of these conditions occur:
1.The connection is explicitly disconnected via the connection's disconnect method directly, or indirectly via the signal's disconnect method, or scoped_connection's destructor.
2.An object tracked by the slot is destroyed.
3.The signal is destroyed.

Alex Guteniev
  • 12,039
  • 2
  • 34
  • 79
  • 1
    Your question seems odd. The signal system doesn't have any idea that you deleted your slot object behind its back. And because you have no state, your object doesn't take up any memory anyway. `MySlot::SlotOne` is a valid function whether or not there are any objects of type `MySlot`. You could do `((MySlot*)0)->SlotOne()`, and it would work just fine. – Tim Roberts Jul 22 '23 at 04:02

1 Answers1

0

The document in boost web says that the disconnection occurs when 'An object tracked by the slot is destroyed.', however, I tested it doesn't work in that way. So I prefer to disconnect manually although it's little bit troublesome.

The key word here is "tracked". Tracking is made by making the slot object inheriting from trackable class:

class MySignal : public boost::signals2::trackable  {
public:
    boost::signals2::signal<void ()> signal_one;
    boost::signals2::signal<void ()> signal_two;
};

Here when you connect like this:

auto c = connect(signal.signal_one, slot, &MySlot::SlotOne);

the signal will have the pointer to slot to track.

Note that with lambda slot you'll have to pass the pointer as an additional parameter, see Using boost::signals2::trackable with lambdas

When you don't track an object lifetime, and call a slot of deleted object, like in your example, you have an Undefined Behavior. Which is still likely to manifest in executing your slot normally, since you don't reference this, and the slot function is nonvirtual.

Alex Guteniev
  • 12,039
  • 2
  • 34
  • 79