[英]C++: Problems reading input from a binary file
我在AccountManagement.cpp中有一个AccountManagement类。 我在Account.cpp中有另一个称为Account的类。 我有一个模板,可以使用OrdereList类对列表中的给定数据进行排序,该类还具有自己的迭代器。 AccountManagement类以二进制文件输出“帐户”列表,如下所示:
void AccountManagement::saveData(const char * file) //saves data in the specified binary file
{
ofstream out(file, ios::out | ios::binary);
if(!out)
{
cerr<<"Problem opening output file!"<<endl;
}
OrderedList<Account>::iterator it = this->account_manager.begin();
for(int i = 0; i < this->total_accounts; i++)
{
Account temp = *it;
out.write((char*)&temp, sizeof(Account));
it++;
}
out.close();
}
我在AccountManagement类中定义了以下函数,该函数从二进制文件读取所有数据并将其输出。 此功能运行良好。 如图所示:
void AccountManagement::output()
{
ifstream in("accounts.dat", ios::in | ios::binary);
if(!in)
{
cerr<<"File doesn't exist!"<<endl;
exit(1);
}
Account acc;
while(in.read((char*)&acc, sizeof(Account)))
{
cout<<acc;
}
in.close();
}
但是,当我在另一个具有Account.h头文件的文件中使用同一函数(名称不同)时,也从同一“ account.dat”文件中检索数据时,这给我带来了分段错误。 可能是什么问题呢? 以下是功能:
void loadData()
{
ifstream in("accounts.dat", ios::in | ios::binary);
if(!in)
{
cerr<<"File doesn't exist!"<<endl;
exit(1);
}
Account acc;
while(in.read((char*)&acc, sizeof(Account)))
{
cout<<acc;
}
in.close();
}
帐户的类别声明:
class Account
{
friend ostream& operator<<(ostream&,const Account&); //overloading << operator
friend istream& operator>>(istream&,Account&); //overloading >> operator
public:
void operator=(const Account&); //overloading = operator
bool operator<=(const Account&); //overloading <= operator
bool operator<(const Account&); //overloading < operator
private:
string number; //Account Number
char name[100]; //Account holder's name
char sex; //M or F indicating the gender of account holder
MYLIB::Date dob; //date of birth of account holder
char address[100]; //address of account holder
char balance[20]; //balance of account holder
};
我不知道MYLIB::Date
类,但是在那里有一个std::string
对象就足够了。
std::string
对象动态分配内存以适合其包含的字符串。 并且在堆上分配的内存仅适用于当前进程,您无法保存指针(位于std::string
类内部)并从其他进程加载它,并希望该指针处将有有效的内存。
如果您在一个进程中保存了指向动态分配的内存的指针,并从另一个进程中加载并使用它,那么您将具有未定义的行为 。
您需要序列化字符串才能保存它。 也可能是MYLIB::Data
对象。
免责声明: 它将在小型嵌入式系统的工作有一个统一的地址映射,遗憾的是所有的投标面向用户的操作系统(如Windows,OSX和Linux)有进程之间独立的地址空间和墙壁。
如果您保存对象并将其再次加载到同一对象中, 并且同时未更改字符串,则您的函数AccountManagement::output()
会给人以完美的印象。
怎么了 ?
一旦您的对象不再是POD对象(即,它包含使用指针或虚拟函数等的数据),您就不能仅通过将其内存写入磁盘来保存它。
在您的情况下,第二个功能由于这个原因而失败。 第一个功能仅给人以实用的印象。 该字符串是一个复杂的对象,该对象在某处存储指向动态分配的内存的指针。 如果您编写对象并照原样读取它,而不更改对象,则只需重新读取内存中的值即可。 读取的隐藏指针的值恰好是读取前的值。 那是非常幸运的情况。 但是在大多数情况下,它将失败。
怎么解决呢?
要保存对象,您应该对其进行序列化:使用适当的功能将每个组件分别写入/读取到文件中。
最简单的方法是使用一些现有的序列化库,例如boost serialization 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.