gpt4 book ai didi

c++ - Boost 分配器的 vector 大小不正确

转载 作者:行者123 更新时间:2023-11-30 03:26:38 25 4
gpt4 key购买 nike

以下程序在内存映射文件的空间内为 c 分配内存,C 类型的对象。将单个字符添加到包含在 c 中的 vector 会将 vector 的报告大小从 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 stretch 上编译代码。

g++ -Wall -pthread  -lboost_system -lboost_filesystem t.cpp -o t

最佳答案

分配器返回原始的、未初始化的内存。

间接通过它,就好像它指向一个 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因此可以按名称检索共享对象(如果您不希望使用 anonymousunique 实例;另请注意,您可以通过相同的名称实例化多个实例)

  • 使用 allocator_type boost 使用作用域分配器适配器(思考:vector<C>)

  • 参数化 C使其易于与标准分配器和共享内存分配器一起使用

  • 使用段管理器指针和分配器实例的隐式转换

  • 隐藏实现细节offset_ptr (90% 的时间你不需要知道)

Live On Coliru

#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

关于c++ - Boost 分配器的 vector 大小不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48181652/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com