我正在用 C++ 编写自定义对象序列化器。我在序列化对象时没有任何问题。但是,反序列化对象后,关闭程序或清理程序时出现错误。我不知道是什么原因导致了这个问题。
错误1:在app.exe中的0x00007FF790BFADED处抛出异常:0xC0000005:访问冲突读取位置0x000001E4E61DBED0
错误2:抛出异常:读取访问冲突。 _Pnext 是 0xFFFFFFFFFFFFFFFF。
#ifndef OBJ_SER_API_H
#define OBJ_SER_API_H
#include <fstream>
class ObjectSerialization
{
public:
/// <summary>
/// Serialize the provided object to a binary file.
/// </summary>
/// <param name="filePath">The path to the binary file where the object will be serialized.</param>
/// <param name="objectToWrite">The object to be serialized.</param>
template<typename T>
static void Serialize(const wchar_t* filePath, const T& objectToWrite)
{
std::ofstream file(filePath, std::ios::binary);
file.write(reinterpret_cast<const char*>(&objectToWrite), sizeof(objectToWrite));
file.close();
}
/// <summary>
/// Deserialize an object from a binary file.
/// </summary>
/// <param name="filePath">The path to the binary file from which the object will be deserialized.</param>
/// <returns>The deserialized object.</returns>
template<typename T>
static T Deserialize(const wchar_t* filePath)
{
T object;
std::ifstream file(filePath, std::ios::binary);
file.read(reinterpret_cast<char*>(&object), sizeof(object));
file.close();
return object;
}
};
#endif // !OBJ_SER_API_H
主要:
#include <iostream>
#include <string>
#include "ObjectSerialization.h"
class Student {
public:
std::wstring Name;
int Age = 0;
};
int main()
{
// Serialization
{
Student student;
student.Name = L"Michael";
student.Age = 22;
ObjectSerialization::Serialize<Student>(L"Student.dat", student);
}
// Deserialization
{
Student student = ObjectSerialization::Deserialize<Student>(L"Student.dat");
std::wcout << student.Name << std::endl;
std::cout << student.Age << std::endl;
} // <- exception occurred
std::cin.get();
return 0;
}
什么原因导致此错误,我应该做什么?
平台:Win10
即使我尝试了所有 C++ 版本,我也收到相同的错误。我做了指针版本,但仍然出现同样的错误。
您不能以这种方式序列化,因为您的自定义对象可能包含指针(如字符串)。
您可能很幸运能够读回您的字符串,因为您正在反序列化在序列化之后并且在同一台机器上。
也许之前使用的内存还没有被其他东西分配(和删除),因此字符串数据仍然在这里。但是,在序列化过程中,指向字符串数据的指针已被释放。 (这并不意味着记忆被删除)。
并且您没有通过反序列化来重新分配它。该指针指向“有效”数据,但是当您的反序列化对象尝试第二次释放它时,您的操作系统会抱怨您的程序不拥有该内存。 (因为您之前已经释放了它)
为了使其成为正确的方法,您应该创建一个接口来在自定义对象上实现,并让您的对象类处理它们的序列化。
类似这样的东西:
class Serializable {
virtual void Serialize(std::ostream) = 0;
virtual void Deserialize(std::istream) = 0;
};
class Student : public Serializable {
virtual void Serialize(std::ostream) override {...}
virtual void Deserialize(std::istream) override {...}
};
}
然后在序列化器类中调用这些函数。