2

我可以依赖在内存映射文件中分配的 boost multi_index_container 吗?这种“数据库”可以在具有相同字节序的计算机之间移植吗?

4

3 回答 3

2

不,这不安全。内存映射文件中第一个字节的地址不能保证在调用之间是相同的。

Boost 的内存映射文件需要一个hint,但这只是一个提示。

所以在第一次调用中,内存可能位于0xBAADF00D. 在第二次调用时,它可能位于0xF00DBAAD. 结构中的指针将不再有效,因为它们将指向内存 around0xBAADF00D而不是 around 0xF00DBAAD

作为一个严重的问题,它通常可能在测试中起作用,因为hint通常可能会遵守 - 但有时该内存地址已经存在东西,并且hint必须忽略。

(还有其他部分让这变得非常困难——但上面的内容让它变得非常不可行)。

现在,像这样的策略可以工作,但需要对所讨论的数据结构进行非常侵入性的内省。为了使数据结构具有正确的偏移量,您必须执行 DLL 重新寻址之类的过程,到那时您还不如将其序列化为平面。

于 2013-01-04T19:44:08.457 回答
1

借助Boost.Interprocess 的内存映射文件并稍加注意,您可以将其持久化multi_index_container;映射位于不同地址的问题可以使用偏移量而不是指针来解决,而 Boost.MultiIndex 已准备好处理该问题:请参阅此示例,其中实现了一种简单的数据库,一次访问多个进程。

这就是说,使用内存映射文件进行持久化是一种非常脆弱的方法,因为它只有在这些参数完全相同的情况下才有效:

  • 机器架构
  • 操作系统版本
  • 编译器版本
  • 编译参数(例如,可能会影响填充)
  • 使用的所有相关库的版本(包括 Boost),因为 ABI 可能会因版本而异
  • 我忘记了其他一些方面:-)

考虑到一切,使用@alfC 建议的Boost.Serialization 可能是跨不同环境的可移植持久性的最佳解决方案。如果您担心速度,像这样的混合方法可能会起作用:

  • 当在同一台机器上使用相同结构的多个进程(理想情况下,在同一个可执行文件之外)的会话和上下文中,内存映射容器。
  • 一旦会话完成(或每隔一段时间以防止崩溃等),使用 Boost.Serialization 可移植地保持。
于 2016-06-02T07:33:24.583 回答
0

如果您想要将multi_index一个计算机从一台计算机传输到另一台计算机,最好的办法是使用 Boost.Serialization,它开箱即用:

http://www.boost.org/doc/libs/1_60_0/libs/multi_index/doc/tutorial/creation.html#serialization

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <fstream>
...
void save(const employee_set& es)
{
  std::ofstream ofs("data");
  boost::archive::text_oarchive oa(ofs);
  oa<<es;
}

void load(employee_set& es)
{
  std::ifstream ifs("data");
  boost::archive::text_iarchive ia(ifs);
  ia>>es;
}
...
employee_set es; // a multi_index type
... // fill it with data
save(es);
...
employee_set restored_es;
load(restored_es);
于 2016-06-01T21:20:59.320 回答