【问题标题】:Serialize complex objetcs using mmap使用 mmap 序列化复杂对象
【发布时间】:2014-07-30 16:02:50
【问题描述】:

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

这个想法是以后能够以这种方式使用 mmap 从文件中加载对象:

my_structure obj = (my_structure)mmap(...)

出于性能目的,无需重新加载所有数据结构(因为它是一个巨大的数据结构!)。 我在互联网上找到的所有示例都非常简化(例如如何将 int 放入文件中......)而且我没有找到任何关于如何编写与包含指针的对象相对应的内存?我们该怎么做呢?

注意:我在 mac osx 上

【问题讨论】:

  • 首先,不要持久化指针,因为它们在重新加载后可能会悬空。
  • @EricZ:我有点猜测这正是他想要使用 mmap 的原因,他可能觉得有一种方法可以为一块内存获取相同的基地址,这将重新加载时使指针开箱即用。
  • 你在google上搜索过“二进制序列化c++”吗?看看下面的答案

标签: c++


【解决方案1】:

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

首先,您不能序列化指针或任何其他非 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);
    }
};

其次,你需要一个特殊的序列化器来计算类/结构中所有成员的偏移量

举个例子,你要序列化struct 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;

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

【讨论】:

  • 这种直接的“内存转储重新加载”技术,用于游戏中。序列化工具对准备好的、预打包的序列化结构进行跨平台对齐,该结构准备好在目标平台上运行时愚蠢地读取,读取后指针固定;并且没有比原始数据块更进一步的分配。完全优化的反序列化,以媒体流的速度完成:)(或几乎)
  • 非常感谢您的回答,我会检查的!
【解决方案2】:

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

您很可能想查看以下页面:

您可能还需要重组您的程序,以便对于序列化数据不使用指针作为成员,因为大多数库都为您规定了合适的可序列化数据结构:它们自己生成的类或纯数据的组合和 STL。

根据数据的性质,您可能想要拆分或分块数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    相关资源
    最近更新 更多