Problems with deserialization using QDataStream.
-
Hello I'm having a lot of problems reading a file back into my QWidget application. It appears that writing/serialization is not an issue as I can verify data via text editor to a degree and my test strings are visible next to the binary data.
When I attempt to load, it appears I freeze at a point where i begin to stream into a QList using a for loop. Using debug I've pinpointed where the program shuts down unexpectedly. I have marked it in the comments of the code I've provided.
Here is my overloaded << data output operator in one class that will be called in another widget class that is set to the central widget. This seems to work great.
QDataStream &operator<<(QDataStream &out, const aCustomWidget *ac) { out << ac->aInt << ac->bInt << ac->AqRect << ac->AqString << ac->qListofInt; qDebug() << "touching ac out << operator"; return out; }
QDataStream &operator>>(QDataStream &in ,aCustomWidget *ac) { //all int are static casted to qint32 in >> ac->aInt >> ac->bInt >> ac->AqRect >> ac->AqString >> ac->qListofInt; qDebug() << "touching ac in << opeators"; ac->prepareDataIn(); //A class that cast items of qint32 back to int return in; }
In my central widget class CenWid I've overloaded << >> operators as such...
I have a QList<aCustomWidget> which i iterate through to store each element...QDataStream &operator<<(QDataStream &out, const CenWid &cw) { int CustomWidget_List_Size =cw.aCustomWidgetList.size(); out << CustomWidget_List_Size; for(int i = 0; i < CustomWidget_List_Size; ++i) { cw.aCustomWidget[i]->prepareDataOutput(); //this is function that static casts int to qint32 aCustomWidget *aCustWid = cw.aCustomWidgetList.at(i); out << aCustWid; } int aMap_size= cw.aMap.size(); //This Map item works great. out << aMap_size; out << cw.aMap; qDebug() << "touching cw out << opeators"; return out; }
Here is my in >> operation code that fails.
QDataStream &operator>>(QDataStream &in, CenWid &cw) { int CustomWidget_List_Size; in >> CustomWidget_List_Size; aMap<int, QLine> aMap; qDebug() << ">> "CustomWidget_List_Size" << IDAList_Size; for(int i = 0; I < CustomWidget_List_Size; i ; ++i) { qDebug() << "entered in for loop"; aCustomWidget *aCustWid = cw.CustomWidgetList.at(i); qDebug() << "1"; in >> aCustWid; //here is where my program fails unexpectedly. qDebug() << "2"; cw.aCustomWidgetList.at(i)->prepareDataIn(); cw.addCustWid(aCustWid); qDebug() << "iterating into CustomwidgetList" << i << "times"; } int aMap_size; in >> aMap_size; in >> aMap; int a = 0; QMapIterator<int, QLine> j(aMap); while(j.hasNext()){ j.next(); cw.aMap.insert(j.key(), j.value()); qDebug() << "iterating into aMap" << a << "times"; ++a; } qDebug() << "touching cw in << opeators"; return in; }
I open a file in MainWindow() as such: The Central Widget class is called aCenWid
void MainWindow::openFile() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open a Tree File"), "", tr("test Files (*.te);; All Files(*)" )); if(fileName.isEmpty()) return; else{ QFile file(fileName); if(!file.open(QIODevice::ReadOnly)){ QMessageBox::information(this, tr("Unable to open file"), file.errorString()); return; } QDataStream in(&file); in.setVersion(QDataStream::Qt_5_9); qDebug() << "in has been set"; aCenWid->clear(); //This is a function that clears all my QList and QMap in my aCenWid class qDebug() << "size of aCustomWidgetList after clear is: " << aCenWid->aCustomWidgetList.size(); in >> *aCenWid; //here I set the input data stream to aCenWid qDebug() <<"size of aCustomWidgetlist is: " << aCenWid.aCustomWidgetList->size(); if( aCenWid->ACustomWidgetList.size() == 0) { QMessageBox::information(this, tr("File is empty"), tr("The File lacks data")); } else{ //we currently dont reach this point. // qDebug() << "aCenWid will now be constructed..."; //aCenWid->reIntCustomWidget(cw); } } }
In addition to addressing my issue I also anticipate needing info on a good method to re-construct once you have reloaded your data if you can shine some light on some of these methods that would be much appreciated. Thanks for looking at my problem.
-
Hello MrJJ thanks for your assistance again.
I get exceptions error of read access violations when I set a break point at the in>> operation.
The code I provided you is for cw.CustomWidget object. I've tried to get around this by using a secondary instance but that seems
to give me the same issues.Hi
So when you stop at break point at
in >> aCustWid
is the aCustWid a valid object ?To get access violation entering the >> the operator
suggests the object instance is invalid/unallocated.This is one of those bugs that are hard to guess at and must be found using the debugger.
- if I change to *aCustWid; I imediately get a semantic error.
Well what error ?
I checked my code and im using *objectptr all the time and if i remove * in from it stops saving the data members.
So i think this is might be important. -
Hi
From quick read of your code i notice
out << aCustWid;aCustWid being a pointer so that will just stream the address of the object and not as expected trigger its << operator.
This is due to the signature being
QDataStream &operator>>(QDataStream &in, CenWid &cw)
(it wants a ref, not a pointer )
so i think you want
out << *aCustWid;
To let the object stream its members. -
Hi I don't think that's the issue if I change to *aCustWid; I imediately get a semantic error. Also I believe streaming out is okay.
-
Hi I don't think that's the issue if I change to *aCustWid; I imediately get a semantic error. Also I believe streaming out is okay.
@JoeJoe_000
Ok as that would really crash hard when you read it in again. :)Looking at your read in code
you read in the list count
in >> CustomWidget_List_Size;
Then you take out a widget from the list
aCustomWidget *aCustWid = cw.CustomWidgetList.at(i);Did you create the widgets before calling the read in function ?
Also did you place break point at
in >> aCustWid; //here is where my program fails unexpectedly.and see what happens. ?
-
Hello MrJJ thanks for your assistance again.
I get exceptions error of read access violations when I set a break point at the in>> operation.
The code I provided you is for cw.CustomWidget object. I've tried to get around this by using a secondary instance but that seems
to give me the same issues. -
Hello MrJJ thanks for your assistance again.
I get exceptions error of read access violations when I set a break point at the in>> operation.
The code I provided you is for cw.CustomWidget object. I've tried to get around this by using a secondary instance but that seems
to give me the same issues.Hi
So when you stop at break point at
in >> aCustWid
is the aCustWid a valid object ?To get access violation entering the >> the operator
suggests the object instance is invalid/unallocated.This is one of those bugs that are hard to guess at and must be found using the debugger.
- if I change to *aCustWid; I imediately get a semantic error.
Well what error ?
I checked my code and im using *objectptr all the time and if i remove * in from it stops saving the data members.
So i think this is might be important. -
Sorry about my lack of information to be honest I don't know a lot about debuging and should proably spend some time learning how to debug. I had to install the CBD installer just to reply to your post.
In anycase what I have found is if I append new items to the list before calling in >> I actually end up loading correctly. so I must I guess I've mistaken how objects are created and need to reassess the process.
To better answer your questions
is the aCustWid a valid object ? - No in my case I had not yet appended and thought thats what was happening in the overloaded operators I still have to append new objects externally for everything to load correctly.
if I change to *aCustWid; I immediately get a semantic error.
Well what error ?I get invalid binary operator errors I believe I can change this around by changing the function prototype parameters.
Thanks again for your assistance.
-
Hi
Ok super
so it was that the list did not contain allocated objects.Well I know using the debugger is not particularly exciting but it does offer help to
find bugs that is hard to catch without it.
So it really is a "must use time on" tool. :) -
No it was good you pointed me in this direction I was sort of ignoring the fact that it was not setup. So yeah thanks again!
-
Just as an FYI for other people who may have the same problem in the future.
My final solution was to add a function to my CenWid &cw object that takes CustomWidget_List_Size; as an argument
and appends this value to the list. I had to do this before inputing my aCusWid object.