以下程序在内存映射文件的空间内为c
(类型为C
的对象)分配内存。向c
中包含的向量添加单个字符会将向量的报告大小从0更改为18446744073709551520.
#include <iostream>
#include <new>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/offset_ptr.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/operations.hpp>
using namespace boost::interprocess;
class C;
typedef managed_mapped_file::segment_manager SegmentManager;
typedef allocator<void, SegmentManager> VoidAllocator;
typedef allocator<char, SegmentManager> CharAllocator;
typedef allocator<C, SegmentManager> CAllocator;
typedef offset_ptr<C> CPtr;
class C {
public:
std::vector<char, CharAllocator> data;
C(const VoidAllocator &voidAlloc) : data(voidAlloc) {}
void add_char() {
std::cout << data.size() << std::endl;
data.push_back('x');
std::cout << data.size() << std::endl;
}
};
int main(int argc, char *argv[]) {
boost::filesystem::remove_all("file");
managed_mapped_file segment(create_only, "file", 100000);
VoidAllocator allocator_instance(segment.get_segment_manager());
CAllocator alloc_c(allocator_instance);
CPtr c = alloc_c.allocate_one();
*c = C(allocator_instance);
c->add_char();
return 0;
}
在堆栈上分配c
时,而不是动态地发生问题。
C c(allocator_instance);
c.add_char();
我使用以下命令使用Boost 1.62和g ++ 6.3.0-18在Debian GNU / Linux上编译代码。
g++ -Wall -pthread -lboost_system -lboost_filesystem t.cpp -o t
答案 0 :(得分:1)
似乎将构造的对象从默认内存池移动到段1会以某种方式混淆向量的实现。使用construct
方法直接在段内存池中构造对象可以解决问题。
CPtr c = segment.construct<C>(anonymous_instance) (allocator_instance);
答案 1 :(得分:1)
分配器返回未初始化的原始内存。
通过它指向类似C
的对象,就像Undefined Behaviour一样。
你当然可以使用placement-new来实现咕噜咕噜的工作:
CPtr c = alloc_c.allocate_one();
new (&*c) C(allocator_instance);
同样,对于非POD(或实际上,非平凡可破坏类型),您必须记住在适当的时间调用析构函数:
CPtr c = alloc_c.allocate_one();
new (&*c) C(allocator_instance);
*c = C(allocator_instance);
c->add_char();
c->~C();
alloc_c.deallocate_one(c);
但正如您已经指出的那样,高级方法避免了新的/删除并使用了段管理器:
CPtr c = segment.construct<C>("Name") (allocator_instance);
使用
find_or_construct
因此可以按名称检索共享对象(如果您不想要,请使用anonymous
或unique
实例;另请注意,您可以通过实例化实例化多个实例同名)
使用allocator_type
有助于使用作用域分配器适配器(想想:vector<C>
)
参数化C
可以很容易地将它与标准分配器和共享内存分配器一起使用
使用段管理器指针和分配器实例的隐式转换
隐藏实施细节offset_ptr
(有90%的时间您不需要了解)
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <iostream>
namespace bip = boost::interprocess;
namespace Shared {
using Segment = bip::managed_mapped_file;
using Manager = Segment::segment_manager;
template <typename T = void>
using Alloc = bip::allocator<T, Manager>;
template <typename T>
using Vector = bip::vector<T, Alloc<T> >;
template <typename Alloc = std::allocator<void> >
struct C {
using allocator_type = Alloc;
bip::vector<char, typename Alloc::template rebind<char>::other> data;
C(Alloc alloc = {}) : data(alloc) {}
void add_char() {
std::cout << data.size() << std::endl;
data.push_back('x');
std::cout << data.size() << std::endl;
}
};
}
int main() {
std::remove("file");
Shared::Segment mmf(bip::create_only, "file", 1000000);
using Alloc = Shared::Alloc<>;
using C = Shared::C<Alloc>;
auto* c = mmf.find_or_construct<C>("byname")(mmf.get_segment_manager());
c->add_char();
//mmf.destroy_ptr(c);
}
打印
0
1