在c语言中第二次读取文件时程序崩溃

Program crash when reading file the second time in c

本文关键字:文件 程序 崩溃 读取 第二次 语言      更新时间:2023-10-16

第二次使用c++文件流读取文件时程序崩溃

嗨,家伙我试图建立一个Qt Gui应用程序,让用户输入所有数据并使用c++文件流将其写入文件。当我试图从文件中读取所有数据时,它第一次工作得很好,但是当我关闭应用程序并试图再次读取它时,我的应用程序崩溃了。我尽我所能去解决它,但我找不到任何解决办法。有人能帮帮我吗?下面是我从文件中读取数据的源代码。

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;

}

下面是将数据写入文件的源代码

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();
    }
}

这是Employee类原型。

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;
};

一个可能的问题:

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

这里FilePath.toStdString()返回临时的std::string,然后调用c_str()并获得指向其数据的指针。然后临时字符串被销毁,然后将悬空指针发送给fstream构造函数!你可以这样做:

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

或直接使用QFile。它以QString作为文件路径。


同时,你不能在void Form::SaveSlot()上删除emp:

Employee *emp = new Employee[row];

(不会导致崩溃,但可能是您想要避免的内存泄漏。)