Boost::managed_mapped_file不能分配所有已增长的空间
boost::managed_mapped_file cannot allocate all of grown space
我试图增长一个内存映射文件,我成功地增长它,但我不能分配我所要求的所有额外空间-我只是得到一个std::bad_alloc
代替。
下面是一个示例,显示了在Linux上使用g++的效果(我在MSVC上的"真实"代码中也看到了相同的效果):
#include <memory>
#include <sstream>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/random_generator.hpp>
namespace
{
using MMapManager = boost::interprocess::basic_managed_mapped_file<
char,
boost::interprocess::rbtree_best_fit<boost::interprocess::null_mutex_family,
boost::interprocess::offset_ptr<void>,
16u>,
boost::interprocess::iset_index>;
using MMapAllocatorType = boost::interprocess::allocator<
std::size_t,
MMapManager::segment_manager>;
using MMapContainerType = boost::interprocess::vector<
std::size_t,
MMapAllocatorType>;
// I've measured this at 256 bytes for my example configuration, but it's not
// documented anywhere, so let's overcompensate
constexpr auto ManagedFileOverhead = 1024u;
boost::filesystem::path getTemporaryFilePath()
{
auto ss = std::stringstream{};
ss << "MMap_test_" << boost::uuids::random_generator{}();
return boost::filesystem::temp_directory_path() / ss.str();
}
}
int main()
{
// Create memory mapped file, initially for 100 items
auto capacity = 100u;
const auto size = (capacity * sizeof(std::size_t)) + ManagedFileOverhead;
const auto path = getTemporaryFilePath();
auto file = std::make_unique<MMapManager>(
boost::interprocess::create_only,
path.string().c_str(),
size);
auto data = file->construct<MMapContainerType>("data_")(file->get_segment_manager());
// Fill with stuff
data->reserve(capacity);
for (auto i = 0u; i < capacity; ++i) {
data->push_back(i);
}
// Let's grow to hold 162 items (100 * golden ratio)
capacity = 162u;
const auto newFileSize = (capacity * sizeof(std::size_t)) + ManagedFileOverhead;
const auto oldFileSize = boost::filesystem::file_size(path);
const auto extraBytes = newFileSize - oldFileSize;
// Unmap from the process, and grow
file.reset();
MMapManager::grow(path.string().c_str(), extraBytes);
// Reopen it to re-map it into this process
file = std::make_unique<MMapManager>(
boost::interprocess::open_only,
path.string().c_str());
data = file->find<MMapContainerType>("data_").first;
// Allocate it all
data->reserve(capacity); // Bang, you're dead
// Close down
file.reset();
boost::system::error_code ec;
boost::filesystem::remove(path, ec);
return EXIT_SUCCESS;
}
将储备(增长后)设置为155项工作,只需多一个就会触发std::bad_alloc
。
为什么不工作?增长是否会在映射文件中产生额外的管理开销,导致我比预期更早地耗尽空间?
您对分配器的假设太多了。
映射文件的增长将在适当的位置发生。向量的增长不会。因此,虽然您只需要在之后增加保留大小的extraBytes
,但在保留期间,您需要足够的空间来容纳新旧分配。
通过使用:
证明MMapManager::grow(path.string().c_str(), oldFileSize + extraBytes);
或者先清空旧容器:
{
auto file = std::make_unique<MMapManager>(boost::interprocess::open_only, path.string().c_str());
file->destroy<MMapContainerType>("data_");
auto data = file->construct<MMapContainerType>("data_")(file->get_segment_manager());
}
MMapManager::grow(path.string().c_str(), extraBytes);
相关文章:
- 是否可以将函数导入命名空间,但不能导出它?
- 链表指针赋值为什么我们不能直接将尾巴分配给 temp 而不是尾巴>尾巴下一个
- 为什么我不能像这样直接将 int 分配给 int 指针:int *p = 6;?
- 不能将类模板中使用的对象的字符串成员变量分配给C++
- 命名空间:不能在没有对象的情况下调用成员函数
- 通用 lambda 不能在命名空间中使用
- 为什么我不能在标头中只定义一个非常量 gloabal 变量?如果我使用命名空间,为什么我必须声明它"extern"?
- 为什么我不能将 new创建的客户端对象分配给unique_ptr
- 为什么我不能将 dlib 中的matrix_exp分配给 std::vector?
- 无法使用名称空间,也不能在我的.h文件中包含标准的C 库
- 为什么const双引用可以分配给int而不能分配给nonconst
- 为什么我不能将该操作员的过载与结构相同的命名空间
- 为什么我不能在以下代码中提供空间作为输入?
- (C++)不能引用命名空间内的枚举类
- 为什么不能引用c++中的嵌入命名空间
- 为什么我不能将命名空间放在父类构造函数调用中?
- 根据标准委员会的说法,为什么匿名名称空间不能充分替代静态名称空间?
- 为什么语句不能出现在命名空间范围内
- 不能将 math.h 放在命名空间中
- "LPVOID"不能分配给 X 类型的实体