Read Access Violation. _Mem was nullptr while assigning QString after calling HeapAlloc() - c++

I have a program that is using HeapAlloc() to allocate a struct that contains a QString and a few QByteArray structs.
Struct code:
struct Environment {
QString internalLinksDomain;
QByteArray aboutTelegram;
QByteArray aboutContacts;
QByteArray aboutFrequent;
QByteArray aboutSessions;
QByteArray aboutWebSessions;
QByteArray aboutChats;
QByteArray aboutLeftChats;
};
My code:
Environment* e = (Environment*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Environment));
e->internalLinksDomain = "Test data";
I have also tried..
e->internalLinksDomain.append("Test data");
Both send me to the atomic file in Visual Studio. I have attached a screen shot of the error and its position in the function causing the error.
VS Error

Related

External vs internal declaration of QByteArray

I have currently some problems with the QSerialPort: When I am using the function from an example which looks like
QKeyEvent *e;
emit getData(e->text().toLocal8Bit());
connect(console, SIGNAL(getData(QByteArray)), this, SLOT(writeData(QByteArray)));
void MainWindow::writeData(const QByteArray &data)
{
qDebug() << "Data is to write: " << data;
serial->write(data);
}
then the receiving device can work with the data. But when I change the function writeData() to
void MainWindow::writeData(const QByteArray &data)
{
QString a = "Q";
QByteArray b = a.toLocal8Bit();
serial->write(b);
}
the receiving device can not work with the received data. Where is the difference between those two approaches?
Update: I found out that apparently the data is only usefully transferred if I press Enter after typing the letters. Somehow the '\n' gets lost in the conversion from QString to QByteArray. How can I keep it?
you should add an enter to your Qstring like this
QString a = "Q\x00D";
In the example you have given, there is no "\n" in the QString! It is not getting lost, it is not there in the first place.
If a newline is necessary, then construct the String as QString a = "Q\n".
You can also construct the QByteArray directly from a character array rather than going through a char array -> QString -> QByteArrray conversion sequence, like so:
QByteArray b("Q\n");
EDIT: I realized that your contrived example where you are just sending the letter "Q" is probably a debug attempt, not your real code. In reality, you're getting data in as a QByteArray from some other signal that is emitting a QByteArray. That QByteArray that you are receiving must not include the newline character in it. If you are reading from a file or user input, then that is normal. Most readline-like functions strip off the trailing newline. If it is always necessary to have a newline, you can simply do something like this in your WriteData method:
void MainWindow::writeData(const QByteArray &data)
{
serial->write(data);
serial->write("\n");
}
If sometimes the passed-in QByteArray has a newline at the end and sometimes not, and your receiving device cannot handle redundant newlines, then you'd need to check whether data ends with a newline and only write the "\n" if it does not.
what if you make the QByteArray like this
QByteArray b(&a);

sending struct via Qt UDP

I am trying to setup two way communication via the QUdpSocket. I am trying to send a struct consisting of a C++ Eigenvector and a double. I have tried serializing into a QByteArray as follows:
MyStruct toSend;
QByteArray buf;
QDataStream s(&buf, QIODevice::WriteOnly);
if (false) s.setByteOrder(QDataStream::LittleEndian);
std::string vec_str = eigenToStr(toSend.vec);
s << (double)toSend.test1 << QString(vec_str.c_str());
Where eigenToStr() converts the Eigenvector to a string.
However, I am unable to read the message on the other end. When I convert back to a string before sending the QByteArray, I get #ffffff. So I assume it's an issue with the QByteArray/QDataStream conversion.
I would appreciate any suggestions as to how I might serialize my struct so that I can send it via UDP.
Thanks!
QByteArray and QDataStream cooperate very well:). If you really want write the raw data to QDataStream , please use the method :
int QDataStream::writeRawData(const char * s, int len)
And personally I prefer to overload << way to write user data to QDataStream, such as
QDataStream& operator <<(QDataStream& out,MyStruct & data)
Then probably code looks as :
MyStruct toSend;
QByteArray buf;
QDataStream s(&buf, QIODevice::WriteOnly);
if (false) s.setByteOrder(QDataStream::LittleEndian);//false ?
s << toSend;

How to convert QImage to QByteArray?

I am trying to create QByteArray from QImage, however although I tried lots of varient, I couldn't handle it.
What I am doing is :
QImage img_enrll; // <--- There is an image coming from another function.
QByteArray arr((char*)img_enrll.bits(),img_enrll.byteCount()); // <-- convertion but I am not sure it is true or not.
funcCheck((unsigned char*)arr.data(), arr.size(), 0, &sam, 1, &n);
virtual Error funcCheck (const uint8_t src[],
size_t src_len,
size_t tout_ms,
IRawSample* dst[],
size_t dst_len,
size_t* dst_n )
However Error code is return Invalid Data. I think that converting QImage to QByteArray is wrong. Please could you kindly help me how to convert to QByteArray?
You could do this:
QImage img_enrll;
QByteArray arr;
QBuffer buffer(&arr);
buffer.open(QIODevice::WriteOnly);
img_enrll.save(&buffer, "yourformat");
Having written that, if you need this for serialization, you are better of with QDataStream.
Try this:
QByteArray arr = QByteArray::fromRawData((const char*)img.bits(), img.byteCount());
In my case I needed a deep copy, so what worked was:
QByteArray arr(img.byteCount(), Qt::Uninitialized) // or resize if it already exists
memcpy(arr.data(), img.constBits(), img.byteCount());

How to save and load a QJsonDocument to a file?

I am trying to learn how to use JSON and the Qt JSON classes. For example I wnat to create a simple QJsonDocument, save it to a file, load it into a different QJsonDocument and compare results.
I managed to create a QJsonDocument. However there is no simple command in the QJsonDocument interface to save it to a file. The same goes for loading the document from a file.
#include <QJsonObject>
#include <QJsonDocument>
#include <QVariant>
int main()
{
QVariantMap map;
map.insert("integer", 1);
map.insert("double", 2.34);
map.insert("bool", QVariant(true));
map.insert("string", "word");
QJsonObject object = QJsonObject::fromVariantMap(map);
QJsonDocument document;
document.setObject(object);
// ?? save document to file
// ?? load file to document
return 0;
}
This answer shows how to load the document by
reading to a QFile
converting QFile to a QString
converting the QString to a QByteArray
constructing the QJsonDocument from the QByteArray
Is there a more straightforward way to do this?
Personally, I think that code [that you linked to] looks a bit messy. Warning: head compiled code follows.
QJsonDocument loadJson(QString fileName) {
QFile jsonFile(fileName);
jsonFile.open(QFile::ReadOnly);
return QJsonDocument().fromJson(jsonFile.readAll());
}
void saveJson(QJsonDocument document, QString fileName) {
QFile jsonFile(fileName);
jsonFile.open(QFile::WriteOnly);
jsonFile.write(document.toJson());
}
This may not be perfect: it assumes QFile instead of QIODevice, but if you're dealing with only local files maybe it won't matter. You can then use these functions instead of repeating the Json load/save code everytime you need to load/save Json.
No need for converting to string and back. With QSettings and QVariant classes you can easily do that. Create QVariant object from QJsonDocument and save it with QSettings. Look at functions QJsonDocument::fromVariant and QJsonDocument::toVariant. Combine them with QSettings class and specifically void QSettings::setValue ( const QString & key, const QVariant & value ) method, that works well with QVariant and that's it.
Also QSettings class has this constructor QSettings::QSettings ( const QString & fileName, Format format, QObject * parent = 0 )
that would allow you to set path to the file - fileName variable

Qt + protobuf, types?

I would like to dip into Google's protocol buffers in Qt development, but I am having trouble figuring out how to incorporate them best.
Ultimately, I want to send with QUdpSocket and QTcpSocket using protocol buffers.
What is the best method for going between a protocol buffer message to sending the data over a socket (QByteArray) and then back again at the other side?
Creating a QByteArray from a protobuf object:
Person person; // a protobuf object
person.set_id(123);
person.set_name("Bob");
person.set_email("bob#example.com");
std::ostringstream out;
person.SerializeToOstream(&out);
QByteArray byteArray(out.str().c_str());
sendSerializedPersonOverQTcpSocket(byteArray);
Reading back a protobuf object from a QByteArray:
QByteArray byteArray = readSerializedPersonFromQTcpSocket();
Person person;
if (!person.ParseFromArray(byteArray, byteArray.size())) {
std::cerr << "Failed to parse person.pb." << std::endl;
}
Instead of:
std::ostringstream out;
person.SerializeToOstream(&out);
QByteArray byteArray(out.str().c_str());
you can also write:
QByteArray byteArray(person.SerializeAsString().c_str());
EDIT: Above two gives the same result, but I'm not sure wether it's correct. This one seems to work better:
QByteArray byteArray(QString::fromStdString(person.SerializeAsString()));
EDIT2: OK, now I know how it works: first two ways are wrong if there are \0 char in serialization - everything after it it's then lost. To correct it one can write:
QByteArray byteArray(person.SerializeAsString().c_str(), person.ByteSize());
Using the code below is really dangerous
std::ostringstream out;
person.SerializeToOstream(&out);
QByteArray byteArray(out.str().c_str());
sendSerializedPersonOverQTcpSocket(byteArray);
You can find a good explanation here In protobuf-c, can optional uint32 variable have value 0
A right way to create a QByteArray from a protobuf message is
QByteArray byteArray;
byteArray.resize(message.ByteSize());
message.SerializeToArray(byteArray.data(), byteArray.size());
#James: You can use ParseFromArray(), for example, as below: (Please note that ParseFromArray() is available only on proto-buf-lite versions of the libs).
void convertQByteArrayToUser(QByteArray& aByteArray)
{
com::your::name_space::User user;
if(!user.ParseFromArray(aByteArray.data(), aByteArray.size()))
{
//could not parse
}
else { //yayyyyy
if(user.has_userid())
{
//...
}
}
}