Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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.


  • Lifetime Qt Champion

    @JoeJoe_000

    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.


  • Lifetime Qt Champion

    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.


  • Lifetime Qt Champion

    @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.


  • Lifetime Qt Champion

    @JoeJoe_000

    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.


  • Lifetime Qt Champion

    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.


Log in to reply