PDA

View Full Version : Reading from TCP Socket crashes program



OnionRingOfDoom
26th January 2006, 20:57
Ok, so I have a program which acts as a server, and can write data to a socket. Now when I use the client program to connect to the server, the client connects just fine, but it crashes whenever it goes to read the data. I'm not entirely sure how the whole QIODevice thing plays into it, but what I wrote makes sense, at least to me :P. Anyway, here's the code:



// Server/Client-related connections
connect(&tcpServer, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
connect(&tcpServer, SIGNAL(connectionAccepted()), this, SLOT(sendSpeed()));
connect(&tcpClient, SIGNAL(connected()), this, SLOT(readSpeed()));

connect(&tcpClient, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(&tcpClient, SIGNAL(state(QAbstractSocket::SocketState)), this, SLOT(displayStatus(QAbstractSocket::SocketState))) ;

// Set up layout
layout->addWidget(connectButton, 0, 0, 1, 2);
layout->addWidget(slider, 1, 0, 1, 2);
layout->addWidget(label, 3, 0);
//layout->addWidget(label2, 3, 0);
layout->addWidget(ipLabel, 5, 0);
win->setLayout(layout);

} // MainWindow()

////////////////////////////////////////////////////////////////////////
// SERVER FUNCTIONS //

// startServer(QString ip, quint16 port) - Starts the server
////////////////////////////////////////////////////////////////////////
void MainWindow::startServer(QString ip, quint16 port)
{
statusBar->showMessage("Server created", 0);
if (!tcpServer.listen(QHostAddress(ip), port))
{
statusBar->showMessage(tr("Unable to start the server: %1.", 0).arg(tcpServer.errorString()));
return;
}
else
{
statusBar->showMessage(tr("Listening on port %1...", 0).arg(tcpServer.serverPort()));
}
}

// acceptConnection() - Completes the connection to the client
////////////////////////////////////////////////////////////////////////
void MainWindow::acceptConnection()
{
slider->setAmpValue(10);
slider->setFreqValue(10);
clientConnection = tcpServer.nextPendingConnection();
statusBar->showMessage("Connection established.", 0);
emit connectionAccepted();
}

// sendSpeed() - Sends the slider speed to the client
////////////////////////////////////////////////////////////////////////
void MainWindow::sendSpeed()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
value = slider->ampValue();

// Write the slider value to the output buffer
out.setVersion(QDataStream::Qt_4_0);
out << value;

// Send the linear slider value to the client
clientConnection->write(block);
}

// SERVER FUNCTIONS

////////////////////////////////////////////////////////////////////////
// CLIENT FUNCTIONS //

// getServer() - Establishes a connection to the server
////////////////////////////////////////////////////////////////////////
void MainWindow::getServer(QString ip, quint16 port)
{
blockSize = 0;
tcpClient.connectToHost(QHostAddress(ip), port);
}

// readSpeed() - Reads the slider speed value into a label
////////////////////////////////////////////////////////////////////////
void MainWindow::readSpeed()
{
QDataStream in(&tcpClient);
in.setVersion(QDataStream::Qt_4_0);

quint8 sliderValue;
in >> sliderValue;
label->setNum(sliderValue);
}

jacek
26th January 2006, 21:19
Could you post the backtrace?

OnionRingOfDoom
26th January 2006, 21:30
Sure! Lemme just figure out how to make MinGW do that

jacek
26th January 2006, 21:36
Sure! Lemme just figure out how to make MinGW do that
You need gdb (http://prdownloads.sf.net/mingw/gdb-5.2.1-1.exe?download) for this.


C:\...\gdb app.exe
(gdb) run
<program crashes>
(gdb) bt
<backtrace>
(gdb) quit

OnionRingOfDoom
26th January 2006, 21:36
Ok, lemme install this doohicky

OnionRingOfDoom
26th January 2006, 21:45
#0 0x10047934 in _size_of_stack_reserve__ ()
Cannot access memory at address 0x200000

that's what it gave me.

jacek
26th January 2006, 22:01
#0 0x10047934 in _size_of_stack_reserve__ ()
Cannot access memory at address 0x200000

that's what it gave me.
Only this? Maybe there was something more?

If there is no main() in the backtrace, it might mean that there is some problem with libraries. Make sure you have "QT += network" in your .pro file.

OnionRingOfDoom
26th January 2006, 22:04
If there is no main() in the backtrace, it might mean that there is some problem with libraries. Make sure you have "QT += network" in your .pro file.

Yep, QT += network" is in the .pro file.

If you want, I can upload the entire source somewhere, and you can see what it does on your end?

jacek
26th January 2006, 22:30
If you want, I can upload the entire source somewhere, and you can see what it does on your end?
According to Murphy's law it will work on my system ;)

Does your program crash before it starts?

OnionRingOfDoom
26th January 2006, 22:32
According to Murphy's law it will work on my system ;)

Does your program crash before it starts?

Nope, I have to start up the program in server mode, then start another instance of the program in client mode. As soon as I click OK on the connect dialog box after typing in the propper port and IP, the server indicates that the client has sucessfully connected, and then the client crashes.

jacek
26th January 2006, 22:46
and then the client crashes.
And there was only one entry in the backtrace? Did you compile your application in debug mode?

Anyway, you try to read data from the socket before they arrive --- you must wait for readyRead() signal.

OnionRingOfDoom
26th January 2006, 22:51
...How do I compile it in debug mode?

jacek
26th January 2006, 22:54
...How do I compile it in debug mode?
Add "CONFIG += debug" to your .pro file (and remove "release" if it's there).

OnionRingOfDoom
26th January 2006, 23:06
Ok so I changed the connection to do the readSpeed() function whenever readyRead() was emitted. However, now nothing happens when the client connects.

I also added a new connection at the end of the acceptConnection() function, which is as follows: connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sendSpeed()));
so now, whenever I move the slider (and it outputs valueChanged signal), it crashes.

OnionRingOfDoom
26th January 2006, 23:30
After further fiddling, it seems that it's not the server's writing to the IO device that's the problem, it's the client's reading from the IO device that's causing the crash. Moving the slider thus causes the server to write data, and the client tries to read it or something, but crashes.

jacek
26th January 2006, 23:42
Does it crash if you change MainWindow::readSpeed() to:
void MainWindow::readSpeed()
{
label->setNum(0);
} ?

Did you try to generate that backtrace again?

OnionRingOfDoom
26th January 2006, 23:49
yes, it still crashes, oddly enough...
and I'm trying to compile in debug mode, but I have to fix all these errors switching to debug mode seems to have created.

OnionRingOfDoom
26th January 2006, 23:55
Oh awesome! It's acting like it can't find the QtNetwork include file anymore...
Any idea why adding that CONFIG thing to the .pro file would make it think it couldn't find QtNetwork, but could still find every other Qt file I included?

jacek
27th January 2006, 00:17
yes, it still crashes, oddly enough...
Is that label variable initialized?


It's acting like it can't find the QtNetwork include file anymore...
Can it find "QTcpSocket? Did you compile Qt in debug mode or maybe you have only release version?

OnionRingOfDoom
27th January 2006, 00:19
First question: yes, it is initialised
And I fixed the other problem, when I remade the .pro file, it didn't put in the
QT += network thing.

OnionRingOfDoom
27th January 2006, 01:21
and now it almost finishes compiling in debug mode... but MinGW comes up with some weird error I'm totally not responsible for:

C:\MinGW\bin\..\lib\gcc\mingw32\3.4.2\..\..\..\..\ mingw32\bin\ld.exe: cannot find -lqtmain

But at least it still compiles in release mode. But it still crashes whenever the client trys to even do anything with the readyRead function.

OnionRingOfDoom
27th January 2006, 03:25
Anyone else got any ideas?

jacek
27th January 2006, 09:55
but MinGW comes up with some weird error I'm totally not responsible for
Did you compile Qt in debug mode? Do you have the libqtmain.a and libqtmaind.a files in %QTDIR%\lib directory?


But it still crashes whenever the client trys to even do anything with the readyRead function.
Does it crash with empty MainWindow::readSpeed()?

Also add "CONFIG += console" to your .pro file and see whether your program outputs something to the console.

OnionRingOfDoom
27th January 2006, 13:47
Does it crash with empty MainWindow::readSpeed()?

Also add "CONFIG += console" to your .pro file and see whether your program outputs something to the console.

No, it does not crash when readSpeed() is empty.
And no, it doesn't write anything to the console.

I'm gonna try to reinstall Qt in debug mode this afternoon, after school

jacek
27th January 2006, 20:15
No, it does not crash when readSpeed() is empty.
Could you post the line in which you initialize that label variable?

OnionRingOfDoom
27th January 2006, 20:25
As for the label, it's initialized like so:


QLabel *label = new QLabel("change");

...............

Wait a sec...... *checks the .h file*

Oh....
I initialised the label variable twice....
**facepalms**
problem solved....

OnionRingOfDoom
27th January 2006, 20:32
Heh, thanks for your help through all this! I tend to have other people ask me some question and then I realise a stupid error I made...