使用mmap序列化复杂对象

Serialize complex objetcs using mmap

本文关键字:对象 复杂 序列化 mmap 使用      更新时间:2023-10-16

我想在c++中使用mmap将一个复杂的对象序列化成二进制文件。我所说的复杂对象是指包含指针的对象(如树状数据结构)。

我们的想法是以后可以用mmap以这种方式从文件中加载对象:
my_structure obj = (my_structure)mmap(...)

不需要重新加载所有的数据结构,出于性能的考虑(因为它是一个巨大的数据结构!)我在网上找到的所有例子都是非常简化的(比如如何在文件中放入一个int…),我没有找到任何关于如何写内存对应于一个包含指针的对象?我们怎样才能做到呢?

注意:我在mac osx上

我见过一种有趣的方法,但它的使用有些限制:

首先,您不能序列化指针或任何其他非POD类型。使用指针引用来序列化结构体的方法是使用一种特殊类型,它不保留指针值,而是保留指针值与其内存位置的偏移量:

的例子:

struct void_ptr
{
    int     offset;
    void * get ()
    {
        return ((char*)this) + offset;
    }
};
//or for generic type:
template <class T>
struct t_ptr
{
    int     offset;
    T * get ()
    {
        return (T*)(((char*)this) + offset);
    }
};
第二,你需要有一个特殊的序列化器来计算类/结构

中所有成员的偏移量。

让我们举个例子,你想要序列化结构体A:

struct A
{
    t_ptr<int>  pointer_to_int;//let's suppose it points to an array of 2 ints      
    int         my_value;
};

这个结构体的总内存需求是16字节或4个int(一个int用于my_value,一个用于pointer_to_int偏移,2个用于int数组指针指向的int指针)pointer_to_int所指向的数组需要位于A结构内存数据之后的内存中,int_ptr的偏移量应该是sizeof(A),因为

的例子:

int m[] = { 8, 1, 2, 3 };
A& a = *(A*)&m[0];
std::cout << a.my_value << std::endl;
std::cout << a.pointer_to_int.get()[0] << std::endl;
std::cout << a.pointer_to_int.get()[1] << std::endl;

在做这样的事情时,了解和处理内存对齐是非常重要的!!

你想做的事情在c++中是危险的。将指针或引用作为成员失败就足够了,因为在反序列化时将无法恢复它们。您将无法直接恢复指针,因为数据地址在运行之间会发生变化。

你很可能想要查看以下页面:

  • 头儿原型
  • msgpack
  • Protocol Buffers

你可能还需要重构你的程序,这样,对于序列化的数据,你不使用指针作为成员,因为大多数库为你规定了一个合适的可序列化的数据结构:要么是他们自己生成的类,要么是普通数据和STL的组合。

根据数据的性质,您可能希望对数据进行分割或分组。