Norin
Norin

Reputation: 13

Program crash when reading file the second time in c

Program crash while reading file the second time using c++ file stream

Hi, guy I was trying to build a Qt Gui application that lets the user inputs all data and write it into file using c++ file stream. And when I try to read all the data back from file it work fine for the first time, but when I close the application and try to read it again my application got crush. I try to fix it the best I can, but I couldn't find any solution. Could anyone help help me. Here my source code for reading data from file.

void Form::OpenSlot()
{
    OpenDialog = new QFileDialog();
    FilePath = OpenDialog->getOpenFileName(this,"Open",AppDir,"Binary Files(*.bin)");
    QString strID, strName, strSex, strSalary, strHour, strRate, strTotal;
    int row = 0;
    Employee *emp = NULL;

    if(!FilePath.isEmpty())
    {
        isNew = false;
        fstream fout(FilePath.toStdString().c_str(),ios::binary|ios::in);

        if(fout.fail())
        {
            msg->setText("Error reading file.\nWrong format.");
            msg->show();
            fout.close();
            return;
        }

        fout.seekg(0,ios::end);
        row = (int)(fout.tellg()/sizeof(Employee));
        fout.seekg(0,ios::beg);
        emp = new Employee[row];
        fout.read((char*)emp,row*sizeof(Employee));
        fout.close();

        for(int i=0;i<row;i++)
        {
            DisplayTable->removeRow(i);
        }

        for(int i=0;i<row;i++)
        {
            strID = QString::number((emp+i)->getID());
            strName = QString::fromStdString((emp+i)->getName());
            strSex = QString::fromStdString((emp+i)->getSex());
            strSalary = QString::number((emp+i)->getSalary());
            strHour = QString::number((emp+i)->getHour());
            strRate = QString::number((emp+i)->getRate());
            strTotal = QString::number((emp+i)->getTotal());

            DisplayTable->insertRow(i);

            DisplayTable->setItem(i,0,new QTableWidgetItem(strID));
            DisplayTable->setItem(i,1,new QTableWidgetItem(strName));
            DisplayTable->setItem(i,2,new QTableWidgetItem(strSex));
            DisplayTable->setItem(i,3,new QTableWidgetItem(strSalary));
            DisplayTable->setItem(i,4,new QTableWidgetItem(strHour));
            DisplayTable->setItem(i,5,new QTableWidgetItem(strRate));
            DisplayTable->setItem(i,6,new QTableWidgetItem(strTotal));
        }
    }
    else
    {
        msg->setText("Can not find path");
        msg->show();
    }

    delete []emp;

}

And here is the source code for writting data into file.

void Form::SaveSlot()
{
    int row = DisplayTable->rowCount();
    // Write Data to file
    if(!isNew)
    {
        fstream fin(FilePath.toStdString().c_str(),ios::binary|ios::out);
        Employee *emp = new Employee[row];

        for(int i=0;i<row;i++)
        {
             emp->setID(DisplayTable->item(i,0)->text().toInt());
             emp->setName(DisplayTable->item(i,1)->text().toStdString());
             emp->setSex(DisplayTable->item(i,2)->text().toStdString());
             emp->setSalary(DisplayTable->item(i,3)->text().toFloat());
             emp->setHour(DisplayTable->item(i,4)->text().toInt());
             emp->setRate(DisplayTable->item(i,5)->text().toFloat());
             emp->setTotal(DisplayTable->item(i,6)->text().toFloat());
             fin.write((char*)&emp,sizeof(Employee));
        }
        fin.close();
    }
    else
    {
        SaveDialog = new QFileDialog();
        FilePath = SaveDialog->getSaveFileName(this,"Save",AppDir,"BinaryFile(*.bin)");

        if(FilePath.isEmpty())
            return;

        fstream fin(FilePath.toStdString().c_str(),ios::binary|ios::out);
        Employee *emp = new Employee[row];

        for(int i=0;i<row;i++)
        {
             (emp+i)->setID(DisplayTable->item(i,0)->text().toInt());
             (emp+i)->setName(DisplayTable->item(i,1)->text().toStdString());
             (emp+i)->setSex(DisplayTable->item(i,2)->text().toStdString());
             (emp+i)->setSalary(DisplayTable->item(i,3)->text().toFloat());
             (emp+i)->setHour(DisplayTable->item(i,4)->text().toInt());
             (emp+i)->setRate(DisplayTable->item(i,5)->text().toFloat());
             (emp+i)->setTotal(DisplayTable->item(i,6)->text().toFloat());
        }

        fin.write((char*)emp,row*sizeof(Employee));
        fin.close();
    }
}

And here is the Employee class prototype.

class Employee
{
public:
    Employee();
    Employee(Employee &emp);
    Employee(int id,string name,string sex,float salary,int hour,float rate,float total);
    void setID(int id);
    void setName(string name);
    void setSex(string sex);
    void setSalary(float salary);
    void setHour(int hour);
    void setRate(float rate);
    void setTotal(float total);
    int getID();
    string getName();
    string getSex();
    float getSalary();
    int getHour();
    float getRate();
    float getTotal();
private:
    int m_id;
    string m_name;
    string m_sex;
    float m_salary;
    int m_hour;
    float m_rate;
    float m_total;
};

Upvotes: 0

Views: 1262

Answers (1)

Guilherme Bernal
Guilherme Bernal

Reputation: 8293

One possible issue:

fstream fout(FilePath.toStdString().c_str(),ios::binary|ios::in);

Here FilePath.toStdString() returns a temporary std::string, then you call c_str() and get a pointer to its data. Then the temporary string is destroyed, and you send the dangling pointer to the fstream constructor! You could do this:

string filePathStr = FilePath.toStdString();
fstream fout(filePathStr.c_str(),ios::binary|ios::in);

Or use QFile directly. It takes a QString for file path.


Also, you are not deleting emp on void Form::SaveSlot():

Employee *emp = new Employee[row];

(does not cause your crash, but is a memory leak you probably want to avoid.)

Upvotes: 1

Related Questions