【问题标题】:C++ program.exe has stopped working after reading from binary file从二进制文件读取后,C++ program.exe 已停止工作
【发布时间】:2013-09-22 15:33:29
【问题描述】:

我创建了一个 Flight 类,其中的信息以另一种方法存储在名为 data.txt 的二进制文件中。记录的保存工作正常,但现在我在读取我保存的记录时遇到问题。它正在显示所有记录,直到文件(eof)结束。但是当记录显示​​完成时,会弹出一个错误,说 Program.exe 已停止工作。

void Flight::ViewFlight(){
HANDLE hConsole;        //Console colors
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
fstream data;
Flight flight;
data.open("data.txt",ios::in | ios::binary);
if (data.fail())
{
    SetConsoleTextAttribute(hConsole, 12);
    cout<<"\n\nFlight data does not exist yet";
    cout<<"\n\nYou are being redirected to the Main Menu in 3 seconds\n\n";
    cout<<"3\n\n";
    Sleep(1000);
    cout<<"2\n\n";
    Sleep(1000);
    cout<<"1\n\n";
    Sleep(1000);
    cout<<"0\n\n";
    SetConsoleTextAttribute(hConsole, 15);
}
else{
    while(data.read((char*) &flight, sizeof(flight)))
    {   
        if(!data.eof())
        {
            SetConsoleTextAttribute(hConsole, 10);
            cout<<"\n\n----------- Record for "<<flight.flightid<<" -----------\n";
            SetConsoleTextAttribute(hConsole, 15);
            cout<<"\nFlight Number \t\t: "<<flight.flightnumber;
            cout<<"\nDeparture Airport\t: "<<flight.departAirport;
            cout<<"\nArrival Airport\t\t: "<<flight.arriveAirport;
            cout<<"\nDeparture Time\t\t: "<<flight.departTime.hour<<":"<<flight.departTime.minute;
            cout<<"\nDeparture Date\t\t: "<<flight.departDate.day<<"/"<<flight.departDate.month<<"/"<<flight.departDate.year;
            cout<<"\nPrice \t\t\t: RM "<<flight.price;
            cout<<"\nBusiness Class Seats\t: "<<flight.bseat;
            cout<<"\nFirst Class Seats\t: "<<flight.fseat;
            cout<<"\nEconomy Class Seats\t: "<<flight.totalseat;
            cout<<endl;
        }
    }
}
data.close();
}

【问题讨论】:

  • Flight 的定义是相关的。
  • 在调试器中运行你的程序,看看哪里出错了。
  • System.exe 中 0x0FABCCC8 (msvcp110d.dll) 处未处理的异常:0xC0000005:访问冲突读取位置 0x004C0754。当我尝试调试它时弹出这个,它是在读取最后一条记录之后。

标签: c++


【解决方案1】:

您的 Flight 类包含 std::string 成员。这些不是普通的旧数据类型,通常保存指向动态分配内存的指针。您不能将班级作为一个单元进行读写,并希望std::string 成员及其内容能够正确构建。这同样适用于TimeData 成员,但您尚未说明它们是如何定义的。

您需要查看正确的serialization

几个相关问题:

【讨论】:

  • @JamesLeng:底线是您不能对std::string 对象进行二进制文件转储。它是一个管理资源(内存)的类,仅写入对象本身并不包括它指向的分配内存。您需要逐个读/写您的课程。在我的回答中添加了一些相关的 SO 问题。
【解决方案2】:

循环似乎很好,您的文件可能包含损坏的数据,可能是未终止的字符串,或者输入文件末尾可能有一些垃圾字符。验证循环中的所有 cout 语句的注释,并查看程序是否停止挂起。 data.eof() 检查也是多余的,但它不应该挂起程序。

【讨论】:

  • 尝试评论所有 cout 语句,仍然有同样的错误。
【解决方案3】:

刚刚看了你的飞行类,你不能直接读入具有其他类对象的类。在您的情况下,字符串对象。您需要对流进行反序列化并自己初始化变量 问题是当飞行被破坏时,它正在破坏那些不是正确构造的字符串对象的字符串对象。 基本上首先将你的字符串从你的缓冲区中分离出来,然后自己一个一个地分配给你的字符串变量。

【讨论】:

    【解决方案4】:

    Flight 结构由指向动态分配的内存(堆)的其他类组成,例如string flightnumber; 是 STL 字符串类,其中包含 char* 或 wchar*。 如果将 Flight 对象保存为二进制缓冲区,它将仅保存指针。在加载对象时,您将在指针中获得内存地址,这是无效的。这就是您收到访问冲突异常的原因,这意味着您尝试访问未分配的内存。

    顺便说一句,最好的情况是你得到 0xC0000005,在最坏的情况下你只会访问分配给其他对象的内存,并在你的输出中得到垃圾。

    你必须为 Flight 类和每个非标准库的类成员重载 operator>。完成后,您只需编写:

    fstream data;
    Flight flight;
    data >> flight;
    

    【讨论】:

      猜你喜欢
      • 2018-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 2023-03-13
      • 2017-10-01
      • 2011-09-03
      相关资源
      最近更新 更多