Discussion:
[Interest] QDataStream null terminated string / Bug or expected behavior?
Etienne Sandré-Chardonnal
2017-02-09 17:18:07 UTC
Permalink
Dear all,

I just found out a bug in my code which was due to the way I wrote/read
from QDataStream.

I write a string like that in one program, from a std::string. This uses
the null-terminated char* overload of << :

std::string str("test");
stream << str.c_str();

I read the data like that in another program:

QByteArray ba;
stream >> ba;

Then ba.size() returns 5 and it contains the null character. Therefore,
comparing it to "test" failed.

In the documentation I cannot find a QByteArray & overload of operator >>.
QByteArray is not supposed to be castable to char*. What is happening here?

Thanks for your help!

Best regards,

Etienne
Mike Chinander
2017-02-09 21:00:02 UTC
Permalink
How are you comparing it to "test" after reading to the QByteArray? You
could use str.data() instead str.c_str(). Or use QStrings to read to/from
the QDatastreams.

On Thu, Feb 9, 2017 at 11:18 AM, Etienne Sandré-Chardonnal <
Post by Etienne Sandré-Chardonnal
Dear all,
I just found out a bug in my code which was due to the way I wrote/read
from QDataStream.
I write a string like that in one program, from a std::string. This uses
std::string str("test");
stream << str.c_str();
QByteArray ba;
stream >> ba;
Then ba.size() returns 5 and it contains the null character. Therefore,
comparing it to "test" failed.
In the documentation I cannot find a QByteArray & overload of operator >>.
QByteArray is not supposed to be castable to char*. What is happening here?
Thanks for your help!
Best regards,
Etienne
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Etienne Sandré-Chardonnal
2017-02-10 15:21:52 UTC
Permalink
I was not comparing directly, but through a QSet<QByteArray>, which was
initially populated using string litterals. So I inserted "test" but after
reading from the stream I had "test\0"
Post by Mike Chinander
How are you comparing it to "test" after reading to the QByteArray? You
could use str.data() instead str.c_str(). Or use QStrings to read to/from
the QDatastreams.
On Thu, Feb 9, 2017 at 11:18 AM, Etienne Sandré-Chardonnal <
Post by Etienne Sandré-Chardonnal
Dear all,
I just found out a bug in my code which was due to the way I wrote/read
from QDataStream.
I write a string like that in one program, from a std::string. This uses
std::string str("test");
stream << str.c_str();
QByteArray ba;
stream >> ba;
Then ba.size() returns 5 and it contains the null character. Therefore,
comparing it to "test" failed.
In the documentation I cannot find a QByteArray & overload of operator
. QByteArray is not supposed to be castable to char*. What is happening
here?
Thanks for your help!
Best regards,
Etienne
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Thiago Macieira
2017-02-09 21:09:34 UTC
Permalink
On quinta-feira, 9 de fevereiro de 2017 18:18:07 PST Etienne Sandré-Chardonnal
Post by Etienne Sandré-Chardonnal
Dear all,
I just found out a bug in my code which was due to the way I wrote/read
from QDataStream.
I write a string like that in one program, from a std::string. This uses
std::string str("test");
stream << str.c_str();
QByteArray ba;
stream >> ba;
Then ba.size() returns 5 and it contains the null character. Therefore,
comparing it to "test" failed.
In the documentation I cannot find a QByteArray & overload of operator >>.
QByteArray is not supposed to be castable to char*. What is happening here?
The two operators are there:
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &);

And they're documented:
http://doc.qt.io/qt-5/qbytearray.html#operator-lt-lt
http://doc.qt.io/qt-5/qbytearray.html#operator-gt-gt

The bug is in your code for marshalling one type and demarshalling another.
That's not guaranteed to work. The behaviour of the two functions is
different. See for yourself:

https://code.woboq.org/qt5/qtbase/src/corelib/tools/
qbytearray.cpp.html#_ZlsR11QDataStreamRK10QByteArray
https://code.woboq.org/qt5/qtbase/src/corelib/io/
qdatastream.cpp.html#_ZN11QDataStreamlsEPKc
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Etienne Sandré-Chardonnal
2017-02-10 15:27:49 UTC
Permalink
Thanks for the link. Yes, I'm doing something bad, but there is no strong
reason to encode a string litteral differently than a QByteArray and not
allowing this. But since retro-compatibility is more important I suppose
this cannot be changed...

Is there a page summarizing all QDataStream >> overloads? They are not in
QDataStream documentation, even as non-members. Seems difficult to find
them all without looking into all the storage classes.
Post by Thiago Macieira
On quinta-feira, 9 de fevereiro de 2017 18:18:07 PST Etienne
Sandré-Chardonnal
Post by Etienne Sandré-Chardonnal
Dear all,
I just found out a bug in my code which was due to the way I wrote/read
from QDataStream.
I write a string like that in one program, from a std::string. This uses
std::string str("test");
stream << str.c_str();
QByteArray ba;
stream >> ba;
Then ba.size() returns 5 and it contains the null character. Therefore,
comparing it to "test" failed.
In the documentation I cannot find a QByteArray & overload of operator
.
QByteArray is not supposed to be castable to char*. What is happening
here?
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &);
http://doc.qt.io/qt-5/qbytearray.html#operator-lt-lt
http://doc.qt.io/qt-5/qbytearray.html#operator-gt-gt
The bug is in your code for marshalling one type and demarshalling another.
That's not guaranteed to work. The behaviour of the two functions is
https://code.woboq.org/qt5/qtbase/src/corelib/tools/
qbytearray.cpp.html#_ZlsR11QDataStreamRK10QByteArray
https://code.woboq.org/qt5/qtbase/src/corelib/io/
qdatastream.cpp.html#_ZN11QDataStreamlsEPKc
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Mike Chinander
2017-02-10 15:33:43 UTC
Permalink
I think it's str.c_str() that's adding the null character at the end of
your string, not anything with QDatastream or QBytearray.

On Fri, Feb 10, 2017 at 9:27 AM, Etienne Sandré-Chardonnal <
Post by Etienne Sandré-Chardonnal
Thanks for the link. Yes, I'm doing something bad, but there is no strong
reason to encode a string litteral differently than a QByteArray and not
allowing this. But since retro-compatibility is more important I suppose
this cannot be changed...
Is there a page summarizing all QDataStream >> overloads? They are not in
QDataStream documentation, even as non-members. Seems difficult to find
them all without looking into all the storage classes.
Post by Thiago Macieira
On quinta-feira, 9 de fevereiro de 2017 18:18:07 PST Etienne
Sandré-Chardonnal
Post by Etienne Sandré-Chardonnal
Dear all,
I just found out a bug in my code which was due to the way I wrote/read
from QDataStream.
I write a string like that in one program, from a std::string. This uses
std::string str("test");
stream << str.c_str();
QByteArray ba;
stream >> ba;
Then ba.size() returns 5 and it contains the null character. Therefore,
comparing it to "test" failed.
In the documentation I cannot find a QByteArray & overload of operator
.
QByteArray is not supposed to be castable to char*. What is happening
here?
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &);
http://doc.qt.io/qt-5/qbytearray.html#operator-lt-lt
http://doc.qt.io/qt-5/qbytearray.html#operator-gt-gt
The bug is in your code for marshalling one type and demarshalling another.
That's not guaranteed to work. The behaviour of the two functions is
https://code.woboq.org/qt5/qtbase/src/corelib/tools/
qbytearray.cpp.html#_ZlsR11QDataStreamRK10QByteArray
https://code.woboq.org/qt5/qtbase/src/corelib/io/
qdatastream.cpp.html#_ZN11QDataStreamlsEPKc
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Glen Mabey
2017-02-10 16:02:04 UTC
Permalink
Thanks for the link. Yes, I'm doing something bad, but there is no strong reason to encode a string litteral differently than a QByteArray and not allowing this. But since retro-compatibility is more important I suppose this cannot be changed...
Is there a page summarizing all QDataStream >> overloads? They are not in QDataStream documentation, even as non-members. Seems difficult to find them all without looking into all the storage classes.
I think you might be looking for this: http://doc.qt.io/qt-5/datastreamformat.html

See also: http://lists.qt-project.org/pipermail/development/2016-September/027302.html

Glen
Thiago Macieira
2017-02-10 16:38:21 UTC
Permalink
Em sexta-feira, 10 de fevereiro de 2017, às 16:27:49 PST, Etienne Sandré-
Post by Etienne Sandré-Chardonnal
Thanks for the link. Yes, I'm doing something bad, but there is no strong
reason to encode a string litteral differently than a QByteArray and not
allowing this. But since retro-compatibility is more important I suppose
this cannot be changed...
Right, there's no good reason. It's an arbitrary difference, but one it's not
worth doing anything about right now. Maybe with a time machine if we could go
back to Qt 3.0 days...

Anyway, QDataStream does not guatantee that you can deserialise a different
type from what you had serialised. So don't. Ever.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Loading...