0

C++ ファイル ストリームを使用して 2 回目のファイル読み取り中にプログラムがクラッシュする

こんにちは、ユーザーがすべてのデータを入力し、c++ ファイル ストリームを使用してファイルに書き込むことができる Qt Gui アプリケーションを構築しようとしていました。そして、ファイルからすべてのデータを読み取ろうとすると、最初は正常に動作しますが、アプリケーションを閉じて再度読み取ろうとすると、アプリケーションがクラッシュしました。最善を尽くして修正しようとしましたが、解決策が見つかりませんでした。誰でも私を助けてくれますか?ここにファイルからデータを読み取るための私のソースコードがあります。

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

1 に答える 1

1

1 つの考えられる問題:

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ファイルパスが必要です。


また、あなたは削除empしていませんvoid Form::SaveSlot():

Employee *emp = new Employee[row];

(クラッシュの原因にはなりませんが、おそらく回避したいメモリ リークです。)

于 2013-06-19T11:47:34.220 に答える