PDA

View Full Version : Signal emit causes segmentation fault



Martikai
25th August 2017, 14:47
I am trying to send a DDS module with the signal-slot method. My program crashes to segmentation fault when it executes the emit signal command. The part of the code where it crashes is inside the moc file and it is:

moc_myclass.cpp:

// SIGNAL 0
void MyClass::MySignal(DDSModule::Message & _t1)
{
void *_a[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}

I have tried to commenting out the connect() part, but the program still crashes so I'm guessing it has something to do with the data I am trying to send. The main code is shown below.

myclass.h:

class MyClass: public QThread
{
Q_OBJECT

signals:
void MySignal(DDSModule::Message &message);

public:
MyClass();
void ddsMessageHandler(DDSModule::Message &message);

protected:
virtual void run();

private:
// Random attributes
};


myclass.cpp:

void MyClass::ddsMessageHandler(DDSModule::Message &message)
{
emit MySignal(message);
}

MyClass::MyClass()
{
}

ddshandler.h:

class DDSHandler : public QThread
{

Q_OBJECT

public:
DDSHandler();
signals:

void DDSDataSend(MyOtherClass *newObject);

public slots:

void handleDDSData(DDSModule::Message &message);

private:
void run();
QCoreApplication *app;

MyClass *myClass_;
};


ddshandler.cpp:

DDSHandler::DDSHandler()
{
myClass_ = new MyClass;
myClass_->start();

qRegisterMetaType<DDSModule::Message &message>("DDSModule::Message &message");

connect(myClass_, SIGNAL(DDSDataReady(DDSModule::Message &message)),
this, SLOT(handleDDSData(DDSModule::Message &message)));
}

void DDSHandler::handleDDSData(DDSModule::Message &message)
{
myOtherClass *messageInNewForm = processMessage(DDSModule::Message &message);

emit DDSDataSend(*messageInNewForm)
}


Is there any restrictions on what type of data I can send with the emit signal? The message that comes to the ddsMessageHandler() is valid. I have also tried removing the reference markers (&) but it doesn't have any effect either.

high_flyer
25th August 2017, 16:19
Well, to start with, your signal is declared as taking a pointer to MyOtherClass yet when you emit the signal you are giving it a copy (a referenced pointer).
There should be at least a warning during compile time for that.
Then, your connect statement tells the signal is taking a reference.
So, decide which is it!

I have tried to commenting out the connect() part, but the program still crashes
Where is it crashing when the connect statement is commented out?

Martikai
28th August 2017, 06:46
Sorry, I forgot to change the signal name to this example when trying to be more abstract. The actual connect() takes the signal MySignal which uses the reference to DDS message instead of DDSDataReady which is not declared anywhere.

The program crashes in the same function whether or not I comment out the connect().

wysota
28th August 2017, 09:01
Sorry, I forgot to change the signal name to this example when trying to be more abstract. The actual connect() takes the signal MySignal which uses the reference to DDS message instead of DDSDataReady which is not declared anywhere.

The program crashes in the same function whether or not I comment out the connect().

Please provide the backtrace and also check if this pointer is not null.

Martikai
28th August 2017, 09:04
I found out that it doesn't matter what i try to send with the emit. I created a whole new test signal that contains an integer which is not connected anywhere and it still causes the exact same segmentation fault.

For some reason the message poster at this forum tells me that my backtrace includes 17 images so I can't post it as it is. I have instead included a screen shot of it.
12571

wysota
28th August 2017, 09:12
Please provide the backtrace from your debugger. The crash is probably caused by either a null pointer dereference or by destroying an object involved in a chain of signal emissions (which boils down to dereferencing an invalid pointer too).

Martikai
28th August 2017, 09:22
The reference is valid when I check it with the debugger. The backtrace is added to my previous message.

high_flyer
28th August 2017, 10:12
I created a whole new test signal that contains an integer which is not connected anywhere and it still causes the exact same segmentation fault.

The backtrace without the code helps very little.
Please post the code that corresponds to the backtrace, and if it is not very long, post all of it, don't "meta code" it as it masks what you are doing wrong.

Martikai
28th August 2017, 10:36
The test signal is not connected anywhere. The crash still happens at the same function after emit which is


// SIGNAL 0
void LidarSub::test(int _t1)
{
void *_a[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}

lidarsub.h:


#ifndef LIDARSUB_H
#define LIDARSUB_H

#include "observation.h"
#include <QThread>
#include <QObject>

#include <ace/Log_Msg.h>

#include <dds/DdsDcpsInfrastructureC.h>
#include <dds/DdsDcpsPublicationC.h>

#include <dds/DCPS/Marked_Default_Qos.h>
#include <dds/DCPS/Service_Participant.h>
#include <dds/DCPS/WaitSet.h>

#include "dds/DCPS/StaticIncludes.h"

#include "/home/vtt/IDL/idl_lidar/lidarScanTypeSupportImpl.h"

class LidarSub: public QThread
{
Q_OBJECT

signals:
void test(int i);

public:
LidarSub();
int create();
void destroy();
void lidarDataConverter(LidarScan::Observation newObs);

protected:
virtual void run();

private:
DDS::DomainParticipantFactory_var dpf_;
DDS::DomainParticipant_var participant_;
DDS::DataReader_var reader_;
LidarScan::ObservationDataReader_var reader_i_;

int numOfRecObs_;

};
#endif // LIDARSUB_H


lidarsub.cpp:


#include "lidarsub.h"

#include <QDebug>
#include <QThread>

#include <ace/Log_Msg.h>

#include <dds/DdsDcpsInfrastructureC.h>
#include <dds/DdsDcpsPublicationC.h>

#include <dds/DCPS/Marked_Default_Qos.h>
#include <dds/DCPS/Service_Participant.h>
#include <dds/DCPS/WaitSet.h>

#include "dds/DCPS/StaticIncludes.h"

#include "/home/vtt/IDL/idl_lidar/lidarScanTypeSupportImpl.h"
#include "/home/vtt/IDL/idl_lidar/DataReaderListenerImpl.h"


using namespace DDS;
using namespace std;

void LidarSub::lidarDataConverter(LidarScan::Observatio n newObs)
{
int i = 0;
emit test(i); // <- This causes the segmentation fault
}

LidarSub::LidarSub()
{
numOfRecObs_ = 0;
}

int LidarSub::create()
{
// OpenDDS related code that initiates the DDS configuration. Can't publish this part of the code on this forum.
// This should not affect anything else than the DDS communication.
}


void LidarSub::destroy()
{
TheServiceParticipant->shutdown();
}

void LidarSub::run()
{
while (true) {

QThread::msleep(10);
}
}




DataReaderListenerImpl.cpp - function that is called when new data arrives through DDS
handle_ is pointer to the instantiation of LidarSub class


void DataReaderListenerImpl::on_data_available(DDS::Dat aReader_ptr reader)
{
LidarScan::ObservationDataReader_var reader_i =
LidarScan::ObservationDataReader::_narrow(reader);

if ( !reader_i )
{
ACE_ERROR((LM_ERROR,
ACE_TEXT("ERROR: %N:%l: on_data_available() -")
ACE_TEXT(" _narrow failed!\n")));
ACE_OS::exit(-1);
}


LidarScan::Observation newObs;
DDS::SampleInfo info;

DDS::ReturnCode_t error = reader_i->take_next_sample(newObs, info);

if (error == DDS::RETCODE_OK)
{

if ( info.valid_data )
{
if ( handle_ != NULL )
{
handle_->lidarDataConverter(newObs);
}
}

} else
{
ACE_ERROR((LM_ERROR,
ACE_TEXT("ERROR: %N:%l: on_data_available() -")
ACE_TEXT(" take_next_sample failed!\n")));
}
}

wysota
28th August 2017, 11:17
Does handle_ point to a valid object?

Martikai
28th August 2017, 11:50
Does handle_ point to a valid object?
No, thank you! I had forgotten about setting the actual pointer. For some reason the DataReaderListenerImpl is able to call the lidarDataConverter() even though the pointer is not a valid object.

wysota
28th August 2017, 12:10
It's a non-virtual function so it doesn't need a proper object to call it. But when you try accessing any data, you end up with reading garbage.