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

Save struct like binary file



  • Hi,

    I have a some problem with crash the application while I try loading the structure from binary file.
    My structure deninition:

    struct Parameters{
    int ID = 0;
    QString name = "Section";
    int temperature_expected = 0;
    };

    I create binary file :

    Parameters parameters;
    
    QFile file(filename);
    if(!file.open(QFile::WriteOnly)){
        qDebug()<<"Cant open file";
        return;
    }
    file.write((char*)&parameters, sizeof(parameters));
    file.flush();
    file.close();
    

    But when i try load file, the application is crashed

    QFile file(path);
    if (!file.open(QIODevice::ReadOnly)){
        qDebug()<<"Cant open load file";
        return false;
    }
    
    QByteArray bytes = file.readAll();
    
    if(bytes.size() != sizeof(Parameters)){
        return false;
    }
    Parameters* parameters = reinterpret_cast<Parameters*>(bytes.data());
    
    return true;
    

    anyone know what could be wrong?



  • @Creatorczyk

    Parameters* parameters = reinterpret_cast<Parameters*>(bytes.data());
    

    You have left parameters pointing into the data() of a QByteArray which has gone out of scope. When you later (presumably) try to read from the content you get rubbish back, including the QString name. If you try to write into *parameters havoc ensues. And you can's store QStrings to file like this anyway.

    Do you still need to do this file stuff in this old way? Serializing (QDataStream) might at least be preferable?



  • Dumping a QString to a file like that won't be useful. It doesn't have the actual "Section" text within the struct, just a pointer. You need to use structs with "plain old data" types and no complicated classes or pointers if you want to be able to usefully persist them like that. If you want text in such a struct, you have to use a simple fixed length character array. If you want variable length text in a binary file, you need a more complicated format where you store a length for the text data used read values one at a time to figure out how long the reads should be..



  • QString stores all its data on the heap so your solution can't work.
    The correct way:

    QDataStream &operator<<(QDataStream& out, const Parameters& par){
    return out << par.id << par.name << par.temperature_expected;
    }
    QDataStream &operator>>(QDataStream& in, Parameters& par){
    return out >> par.id >> par.name >> par.temperature_expected;
    }
    

    QFile file(filename);
    if(!file.open(QFile::WriteOnly)){
        qDebug()<<"Cant open file";
        return;
    }
    QDatastream writeStream(&file);
    writeStream << parameters;
    

    QFile file(path);
    if (!file.open(QIODevice::ReadOnly)){
        qDebug()<<"Cant open load file";
        return false;
    }
    Parameters parameters;
    QDatastream readStream(&file);
    readStream >> parameters;
    

    See https://doc.qt.io/qt-5/qdatastream.html


Log in to reply