GCC下的对象加载段错误
Object loading segfault under GCC
这些方法应该保存和加载与它们相关联的整个对象。当我通过gcc在Linux下编译程序时,保存似乎可以工作,但在加载时它会出现分段错误。当我在Windows下通过Visual Studio编译器编译它时,它就像梦一样工作。我不确定有什么不同,但我有一种预感,它涉及到一些奇怪的gcc。
两种方法:
void User::SaveToFile()
{
ofstream outFile;
string datafile_name = username + "_data";
outFile.open(datafile_name.c_str(), ios::binary);
outFile.write((char*)this, sizeof(*this));
}
void User::LoadFromFile(string filename)
{
ifstream inFile;
inFile.open(filename.c_str(), ios::binary);
inFile.read((char*)this, sizeof(*this));
}
声明:
class User
{
private:
string username;
string realname;
string password;
string hint;
double gpa;
vector<Course> courses;
public:
double PredictGPA();
void ChangePassword();
void SaveToFile();
void LoadFromFile(string filename);
void SetUsername(string _username){username = _username;}
string GetUsername(){return username;}
void SetRealname(string _realname){realname = _realname;}
string GetRealname(){return realname;}
void SetPass(string _password){password = _password;}
string GetPass(){return password;}
void SetHint(string _hint){hint = _hint;}
string GetHint(){return hint;}
};
您的class User
不是POD类型,它不是普通的旧数据类型(如C结构体)。你不能只是按位读写它的内存并期望它能工作。string
和vector
都不是pod,它们保留指向动态分配数据的指针。当读取这些回读时,试图访问无效内存将导致段错误。更重要的是,string
和vector
的内容实际上根本没有被保存,因为它们不在对象的内存布局中(它有时可能与string
和SBO一起工作,但它只是偶然的,仍然没有定义这样做)。
你需要一种方法来序列化和反序列化你的类;当你像那样读入类时,你的类不可能神奇地变成一个对象。
相反,你需要提供你在加载/保存类时调用的函数,这些函数以你选择的某种格式存储类,例如XML。
所以不用
outFile.write((char*)this, sizeof(*this));
有一些成员函数将其转换为具有加载时可以轻松解析的格式的字符串(或您认为更容易的二进制格式),然后保存它。
outFile.write(this->myserialize(), mysize);
你不能那样写进string
。一方面,它通常动态地存储数据,也就是说,它根本不在对象内部;另一方面,你不必依赖于它的任何特定布局。
向量也有类似的问题,你似乎根本没有考虑到端序和填充。
简单地说,你在做不成立的假设。
一般来说,不要在字节级别上混淆复杂(非pod)对象。用某种文本格式序列化,使用对象的公共成员函数来提取和恢复它们的状态。
你考虑过JSON吗?
字符串等可能包含指针——在这种情况下,你的方法可能会出现严重的错误。
您需要序列化数据-即将其转换为一系列字节。
当读取数据时,您只需读取字节,然后从中创建对象。新的指针将是正确的
如果你坚持这个路线,我会写字符串的长度,而不是null终止它。在装载时更容易分配。在二进制格式中有很多需要考虑的问题。每个字段都应该有某种类型的ID,以便在错误的位置或不同版本的程序中可以找到它。此外,在你的文件开始写你正在使用的尾序和你的整数的大小等。或者为所有东西确定一个标准的大小和顺序。我以前总是这样编写网络和文件存储的代码。有更好的现代方法。还可以考虑使用缓冲区并创建Serialize()函数。
好的现代替代品包括:SQLite3, XML, JSON
未经测试的例子:
class object
{
Load()
{
ifstream inFile;
int size;
inFile.open("filename", ios::binary);
inFile.read(&size, 4);
stringA.resize(size);
inFile.read(&stringA[0], size);
inFile.read(&size, 4);
stringB.resize(size);
inFile.read(&stringB[0], size);
inFile.close(); //don't forget to close your files
}
Save()
{
ofstream outFile;
int size;
outFile.open("filename", ios::binary);
size = stringA.size();
outFile.write(&size, 4);
outFile.write(&stringA[0], size);
size = stringB.size();
outFile.write(&size, 4);
outFile.write(&stringA[0], size);
outFile.close();
}
private:
std::string stringA
std::string stringB
};
- 为什么PyImport_ImportModule python 3.7.2 中出现段错误?
- 为什么在访问 vtkRenderWindow 的"交互器"变量时会发生段错误?
- 全局向量导致 C++ 程序结束时出现段错误
- 为什么重载运算符<<打印特征类成员会导致段错误?
- 更改条件段错误
- 使用 TTF_RenderText() 加载字体时获取段错误 TTF_OpenFontRW()
- 注册对对象工厂的调用会导致段错误
- pthread_create在构造函数段错误中
- Nanoflann发现邻居提出段错误
- C++ 中的构造函数、继承、堆栈、堆、this-pointer 和段错误
- 具有unique_ptr的 CRTP 会导致段错误
- 增强纤维work_stealing屏障会导致段错误
- 当我返回指向结构的指针向量时出现段错误
- C++为什么我的代码没有爆炸/段错误?
- Pthread段错误,使用指向main中变量的指针
- C++ 模板中的段错误
- 相当于Windows/MSVC上的段错误?
- 为什么我的 LLVM JIT 实现出现段错误?
- 为什么访问我的引用捕获变量会导致我的 lambda 函数出现段错误?
- 为什么自删除的全局 Vulkan 实例仅在添加层时才导致段错误?