【问题标题】:Why does boost's managed_mapped_file :: shrink_to_fit behave differently on Windows and Linux?为什么 boost 的 managed_mapped_file :: shrink_to_fit 在 Windows 和 Linux 上的行为不同?
【发布时间】:2017-10-27 08:40:17
【问题描述】:

这是关于 C++ 库的提升。

managed_mapped_file :: shrink_to_fit 函数在 Linux 和 Windows 上的工作方式不同。

在 Linux 上,即使目标实例存在,此函数也会成功。 但是,在 Windows 上,如果目标实例存在,此函数将失败。

这是正确的行为吗?

做同样的行为似乎是正确的,这是一个错误吗?

我把示例代码放在下面。

编译环境

  • boost:version.1.65.1

  • 窗户

    • VisualStudio2017
    • WSL(Ubuntu16.04)
  • Linux

    • UbuntuServer17.10,
    • Clang++5.0,
    • g++7.2.0

编译

clang++-5.0 -std=c++1z ./test.cpp -o test -lpthread

#define BOOST_DATE_TIME_NO_LIB
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <vector>
#include <iostream>
namespace bip = boost::interprocess;
using intAlloc = bip::allocator<int, bip::managed_mapped_file::segment_manager>;
using intVec = std::vector<int, intAlloc>;

int main() {
    bip::managed_mapped_file *p_file_vec;
    intVec *vecObj;

    std::string fileName = "tmp.dat";
    size_t fileSize = 1024 * 1024 * 1;
    bip::file_mapping::remove(fileName.c_str());

    p_file_vec = new bip::managed_mapped_file(bip::create_only, fileName.c_str(), fileSize);
    vecObj = p_file_vec->construct<intVec>("myVecName")(p_file_vec->get_allocator<int>());
    for (size_t i = 0; i < 10; i++)
    {
        vecObj->push_back(1 + 100);
    }
    p_file_vec->flush();

    try
    {   //Fail when execute on Windows(WSL),but Success on Linux(Ubuntu17.10).
        std::cout << "try to shrink:pointer has existed yet!" << std::endl;
        bip::managed_mapped_file::shrink_to_fit(fileName.c_str());
        std::cout << "success to shrink!" << std::endl;
    }
    catch (const boost::interprocess::interprocess_exception  &ex)
    {
        std::cerr << "fail to shrink!" << std::endl;
        std::cerr << ex.what() << std::endl;;
    }
    std::cout <<"please pless enter key."<< std::endl;
    std::cin.get();

    try
    {   //Success when execute on Windows(WSL) and Linux(Ubuntu17.10).
        delete p_file_vec;
        std::cout << "try to shrink:pointer has deleted!" << std::endl;
        bip::managed_mapped_file::shrink_to_fit(fileName.c_str());
        std::cout << "success to shrink!" << std::endl;
    }
    catch (const std::exception& ex)
    {
        std::cerr << "fail to shrink!" << std::endl;
        std::cerr << ex.what() << std::endl;;
    }
    std::cout << "please pless enter key." << std::endl;
    std::cin.get();
}

【问题讨论】:

    标签: c++ linux boost


    【解决方案1】:

    不要在 C++ 中使用 newdelete(经验法则)。

    除此之外

        delete p_file_vec;
    

    不会删除任何物理内容。它有效地与映射文件断开连接。这也是shrink_to_fit 起作用的原因:the documentation explicitly says

    如果应用程序可以找到没有附加任何进程的时刻,它可以增长或缩小以适应托管段。

    还有here

    所以,简而言之:行为在两个平台上都是正确的。当您在使用映射文件时(在 Ubuntu 上)收缩时,您的情况会发生什么,这只是未定义的。

    固定代码:

    Live On Coliru

    #include <boost/interprocess/managed_mapped_file.hpp>
    #include <iostream>
    #include <vector>
    
    namespace bip = boost::interprocess;
    using intAlloc = bip::allocator<int, bip::managed_mapped_file::segment_manager>;
    using intVec = std::vector<int, intAlloc>;
    
    int main() {
        std::string const fileName = "tmp.dat";
        bip::file_mapping::remove(fileName.c_str());
    
        {
            bip::managed_mapped_file file_vec(bip::create_only, fileName.c_str(), 1l << 20);
            auto *vecObj = file_vec.construct<intVec>("myVecName")(file_vec.get_allocator<int>());
    
            for (size_t i = 0; i < 10; i++) {
                vecObj->push_back(1 + 100);
            }
        }
    
        try { // Success when execute on Windows(WSL) and Linux(Ubuntu17.10).
            std::cout << "try to shrink:pointer has deleted!" << std::endl;
            bip::managed_mapped_file::shrink_to_fit(fileName.c_str());
            std::cout << "success to shrink!" << std::endl;
        } catch (const std::exception &ex) {
            std::cerr << "fail to shrink!" << std::endl;
            std::cerr << ex.what() << std::endl;
            ;
        }
    }
    

    【讨论】:

    • 非常感谢。你的回答解决了问题。但是如果我需要动态分配变量呢?
    猜你喜欢
    • 2012-11-11
    • 2011-01-03
    • 1970-01-01
    • 2021-04-26
    • 2019-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-05
    相关资源
    最近更新 更多