2016-09-29 36 views
1

我想增長一個內存映射文件,我成功增長了它,但我無法分配所有額外的空間我請求 - 我只是得到一個std::bad_alloc而不是。boost :: managed_mapped_file不能分配所有的增長空間

這裏是顯示了在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

爲什麼這不起作用?增長是否會在映射文件中產生額外的管理開銷,導致我的空間用完時間超出預期?

回答

3

你只是簡單地假設分配器太多。

增長映射文件將發生。增加矢量不會。所以,雖然你只需要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); 
相關問題