Folks,
I have a new problem. I have a class with a short lifespan. It creates a reader in its constructor, and deletes it automatically in the destructor. The class itself acts as the listener:
template<class Topic> PushReader : public dds::sub::NoOpDataReaderListener<Topic>{ public : PushReader(); virtual ~PushReader(); private : dds::sub::DataReader<Topic> _reader; void on_data_available(dds::sub::DataReader<Topic> &reader);} template<class Topic> PushReader<Topic>::PushReader() : _reader(dds::core::null){ // Create _reader and set this as the listener} template<class Topic> PushReader<Topic>::~PushReader(){ if( _reader != dds::core::null ) { if( _reader.get_listener() != nullptr ) { _reader.set_listener(nullptr); } }}
The class I use is derived from PushReader. When it is deleted, I get a Seg Fault from the set_listner line. If I comment out the set_listener line, it Seg Faults at the end of the destructor.
So the question is : What am I doing wrong for this to happen ? According to the set_listener documentation setting it to null is how a listener is removed.
Dale Pennington
In what thread are you deleting the PushReader object?
It is in the main thread, same thread where it is created.
Basically I am creating an object in the main thread, which in turn creates the PushReader based object, works a little with it, then deletes it.
Dale
How are you setting the listener? Make sure you're not doing this:
shared_ptr<>(this)
(See https://en.cppreference.com/w/cpp/memory/enable_shared_from_this for an explanation why that will crash).
I would recommend to make the listener a separate class. You can define it inside PushReader to keep it hidden.
<edit correction> I am using a shared point, as that is the example and required by the interface. I cannot just do set_listener(this)
I could certainly do the other approach, but that looked like much more complicated code to pass along. Especially given the levels of inheritance I am using. And at some point we have to pass from PushReader back to the caller.
I am putting together a quick test program to do create/.destroy to see if I can recreate in a simple environment.
Dale
Yes, you need to pass a shared pointer to the "set_listener()" method. But as Alex wrote, you can't do that with a "this" pointer in the way that you're doing it...it's not a DDS issue, it's how C++ works.
Here's a file (see attachment) that shows how to do it with a internal Listener class inside of PushReader. I've compiled and tested and it works (with deletion w/o segfault).
Here's another version in which the internal Listener class calls PushReader::on_data_available()...should you want the parent class to actually implement the callback.
Thanks for the feedback. That helps clear things up
Dale