指针不能直接持久化到文件中,因为它们指向绝对地址。为了解决这个问题,我编写了一个relative_ptr
模板,它保存了偏移量而不是绝对地址。
基于只有平凡复制的类型才能安全地按位复制的事实,我做出了这种类型需要是平凡复制的假设,以便在内存映射文件中安全地持久化并在以后检索。
这种限制后来证明有点棘手,因为编译器生成的复制构造函数没有有意义的行为。我发现没有任何禁止我将复制构造函数默认设置为私有并使其成为私有的,以避免意外的复制导致未定义的行为。
后来,我发现了boost::interprocess::offset_ptr
,它的创建也是出于同样的需求。然而,结果表明,offset_ptr
并不是平凡复制的,因为它实现了自己的自定义复制构造函数。
我的假设是智能指针需要是平凡复制的才能安全地持久化吗?
如果没有这样的限制,我想知道是否也可以安全地执行以下操作。如果不行,那么类型必须满足哪些要求才能在上述场景中使用?
struct base {
int x;
virtual void f() = 0;
virtual ~base() {} // virtual members!
};
struct derived : virtual base {
int x;
void f() { std::cout << x; }
};
using namespace boost::interprocess;
void persist() {
file_mapping file("blah");
mapped_region region(file, read_write, 128, sizeof(derived));
// create object on a memory-mapped file
derived* d = new (region.get_address()) derived();
d.x = 42;
d->f();
region.flush();
}
void retrieve() {
file_mapping file("blah");
mapped_region region(file, read_write, 128, sizeof(derived));
derived* d = region.get_address();
d->f();
}
int main() {
persist();
retrieve();
}
感谢所有提供替代方案的人。由于我已经有一个可行的解决方案,所以我不太可能很快使用其他东西。正如您从上面的问号使用中可以看出的那样,我真的很想知道为什么 Boost 可以不使用平凡可复制的类型,并且你能走多远:很明显具有虚成员的类将无法工作,但是在哪里划线呢?
x.foo
,那么y.foo
也会改变。尽管它们由于 mmap 具有不同的地址,但它们是同一个对象。 - deft_code