PDA

View Full Version : Code compiled on Qt 4.6.3 does not work on Qt 4.7.0



frikkasoft
13th December 2011, 13:19
I have a client which serializes a bunch of Qimages using QDatastream through QTcpSocket to a server for processing. Using similar code to which are in the Qt demo examples.

The binaries were compiled using Qt 4.6.3 (2010.04) and everything works great if the server runs on Qt 4.6.3 but if its run on Qt 4.7.0 (2010.05) the data which the server reads from the socket gets corrupt. It does not matter if the client and server are on the same machine using localhost.

The protocol I have is: [nrBytes, Qimage1], [nrBytes, Qimage2], ..., [nrBytes, QimageX] and at some random position the nrBytes will get corrupt and be an almost random value. nrBytes is a quint32 both on the client and server side.

I thought this was some bug in my code but after spending almost 5 days on debugging the code, involving several other programmers we can not see anything wrong. So I thought this was a hardware issue but after replacing almost all components this error still occurrs.

I then thought about binary compatibility but after reading Qt 4.7.0 changelog (http://qt.nokia.com/products/changes/changes-4.7.0) it says:
"The Qt version 4.7 series is binary compatible with the 4.6.x series. Applications compiled for 4.6 will continue to run with 4.7."

So I am quite stumped why the data gets corrupt since this should work, right?

MarekR22
13th December 2011, 14:43
Read carefully QDataStream documentation, especially section about versioning!.
Quick fix just call QDataStream::setVersion(QDataStream::Qt_4_6) when creting your QDataStream.
If I remember correctly they change way of recording floating point numbers (float and double are always write in same format controlled by QDataStream::setFloatingPointPrecision).

edit:
now I'm confused too. Apparently they didn't do anything fancy in version 4.7 (last change there was in version 4.6), are you sure that it was 4.6->4.7 transit, not 4.5->4.7?

edit 2:
I've check history of QDataStream source code here (https://qt.gitorious.org/qt/qt/blobs/history/4.7/src/corelib/io/qdatastream.cpp).
There no changes after 4.6 except "Update licenseheader text in source files" and "Update copyright year to 2011." so no impact on code functionality at all.

frikkasoft
13th December 2011, 15:24
Quick fix just call QDataStream::setVersion(QDataStream::Qt_4_6) when creting your QDataStream.
Yes I already do this.

Its maybe best if I show some actual code. Here the client sends the data to the server:


// write header to socket
for( int i=0; i<frames.size(); i++ ) {
QFileInfo fi = frames.at(i);
QImage image(fi.absoluteFilePath());
QByteArray block2;
QDataStream stream2(&block2, QIODevice::WriteOnly);
stream2.setVersion(QDataStream::Qt_4_6);
stream2.setByteOrder(QDataStream::LittleEndian);
stream2 << quint32(0) << image;
stream2.device()->seek(0);
stream2 << quint32(block2.size() - sizeof(quint32));
socket.write(block2);
socket.flush();
socket.waitForBytesWritten();
}


And here is the code where the server reads the data:


QDataStream in(&socket);
in.setByteOrder(QDataStream::LittleEndian);
in.setVersion(QDataStream::Qt_4_6);
// read header from socket
for( int i=0; i<nrFrames; i++) {
quint32 nrBytes;
QImage image;
waitForBytes(&socket, sizeof(quint32), 30000); // wait max 30 seconds on socket until sizeof(quint32) has arrived on socket
in >> nrBytes;
qDebug() << "nrBytes: " << nrBytes;
waitForBytes(&socket, nrBytes, 30000); // wait max 30 seconds on socket until nrBytes has arrived on socket
in >> image;
// process image
}


Here is an example output what happens when the server is running on QtSdk 2010.05:



nrBytes: 39232
nrBytes: 38512
nrBytes: 40923
...
nrBytes: 2043430232


Obviously a single QImage is less than 2GB so the waitForBytes function timeouts and the socket closes. But I must say this is really strange that this happens because this code has been unchanged and has run on several production servers for almost 2 years without problems.

Note: I dont know if this is related with the data corrupt issue I was describing, but when trying the code on another machine with qtsdk-2010.05 the server outputs:
"Reading ras files from sequential devices not supported"
each time it reads a qimage and the image. I am sending Qimage instances loaded from PGM files if that makes any difference.

MarekR22
14th December 2011, 09:29
Was read form socket successful?
This value looks like some garbage.
Improve logs and set initial value for nrBytes.
You are handling reading from socket in strange way, what is this waitForBytes?