PDA

View Full Version : Segmentation fault when try to send message



brevleq
6th January 2009, 17:37
I'm having a seg fault problem that I don't know how solve it.
I have a client program with a lot of QSpinBox, some of them was promoted to a custom class SpinView. When someone change the value in SpinView it automatically call a function of my SocketManipulation class to send the change to gateway application, but when the SocketManipulation try to send it returns a seg fault.
I've compared the memory address of SocketManipulation instance and this is the same, stopped the read of socket cause I was thinking they was accessing the socket at the same time, checked the message passed and the size of it but the same problem is happening!
I think the problem isn't in SocketManipulation function cause I called it manually and it works!
What could be it?
These are the codes:


#include "SocketManipulator.h"
#include <QStringList>

#include <iostream>

using namespace std;

SocketManipulator::SocketManipulator(QObject *parent, QString h, int p): QThread(parent){
hostName=h;
porta=p;
piorCasoLeitura=45;
piorCasoEscrita=12;
socket = new QTcpSocket(NULL);
socket->setReadBufferSize(piorCasoLeitura);
socket->connectToHost(hostName, porta);
start();
}

SocketManipulator::~SocketManipulator(void){
if(socket!=NULL)
delete(socket);
}

QList<int> SocketManipulator:: getdIn(){return dIn;}
QList<int> SocketManipulator:: getdOut(){return dOut;}
QList<int> SocketManipulator:: getaIn(){return aIn;}
QList<int> SocketManipulator:: getaOut(){return aOut;}
QList<int> SocketManipulator:: getaTypes(){return aTypes;}

void SocketManipulator::requestWrite(QString msg){
socket->write(msg.toStdString().c_str(),50/*piorCasoEscrita*/);
}

void SocketManipulator::run(void){
while(true){
socket->waitForReadyRead();
read();
// requestWrite("Idiota!\n");
}
//sign:1,1
//unsign:1,1
}

void SocketManipulator::read(void){
QString msg;
if(socket->bytesAvailable() >= piorCasoLeitura)
msg=socket->read(piorCasoLeitura);
cout<<"Mensagem recebida: "<<msg.toStdString();
processMsg(msg);
}

void SocketManipulator::processMsg(QString msg){
QStringList lista;
QString type;
QList<int> values;
values.clear();
lista = msg.split(":");
type=lista.value(0);
lista=lista.value(1).split(";");
for(int cont=0; cont<lista.size(); cont++)
values.append(lista.value(cont).toInt());
if(type=="aOut"){
aOut=values;
emit receivedAOut();
}
if(type=="aIn"){
aIn=values;
emit receivedAIn();
}
if(type=="dIn"){
dIn=values;
emit receivedDIn();
}
if(type=="dOut"){
dOut=values;
emit receivedDOut();
}
if(type=="aTypes"){
aTypes=values;
emit receivedATypes();
}
}



#include "SpinView.h"

SpinView::SpinView(QWidget *parent):QSpinBox(parent){
connect(this,SIGNAL(valueChanged(int)),this,SLOT(s etOutValue()));
}

void SpinView::setSocket(SocketManipulator *s){
socket=s;
}

QString SpinView::createMessage(){
QString message;
QString aux;
QStringList lista=this->objectName().split("Spin");
if(lista.value(0)=="aOut")
message="setAOut:";
else
message="setDOut:";
message+=aux.setNum(this->value());
message+=";";
message+=lista.value(1);
return(message);
}

void SpinView::setOutValue(void){
socket->requestWrite(createMessage());
}


Another thing I forgot to tell you. When I run the application this message is shown:


QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x81511b0), parent's thread is QThread(0x807b390), current thread is SocketManipulator(0x8150ee8)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x81511b0), parent's thread is QThread(0x807b390), current thread is SocketManipulator(0x8150ee8)

Perhaps this is the problem but I don't know how to solve it to!

jpn
6th January 2009, 17:50
What do you need threads for? QTcpSocket works asynchronously unless you use those blocking waitXXX() methods.

Your problem is that the constructor of SocketManipulator is executed in the thread that creates it. Later on QThread starts a new thread when you call start() and the run() function gets executed in the newly started thread. Currently you create the socket in one thread (in constructor) and use it in different thread (in run). This is a no no. You should create the socket in run().

brevleq
6th January 2009, 19:28
I did what you said. The warning messages aren't shown right now but the seg fault still happens!!

jpn
6th January 2009, 19:42
Why don't you answer my first question? It's one of the most common mistakes to use threads with Qt sockets even if it's completely unnecessary in simple cases. Qt sockets are asynchronous. They don't block the GUI. Using threads just makes things a lot more error-prone as you have already noticed.

The next problem is that you use direct calls to communicate between two threads. Your thread class should enter to an event loop, and then you should use signals and slots or custom events to deliver the message to be written to the correct thread.

brevleq
6th January 2009, 21:32
This program is a simple client, it receives a lot of data and sometimes it should messages to set in gateway what type of message it will receive.

I changed the class of socket, now it isn't inheriting QThread, but...
the seg fault still happen!

I was looking that others parts of the program can send messages well, just when I set in user interface the SpinView it crashes in the function used to send.

brevleq
7th January 2009, 01:10
I've reimplemented SpinView and it's sending messages now!

Thanks