boost::interprocess 共享内存段函数 find() 如果段已经存在,则在启动时挂起

Posted

技术标签:

【中文标题】boost::interprocess 共享内存段函数 find() 如果段已经存在,则在启动时挂起【英文标题】:boost::interprocess shared memory segment function find() hangs at startup if the segment is already there 【发布时间】:2014-07-29 22:11:46 【问题描述】:

我正在尝试使用 boost 的共享内存功能将向量放入共享内存中,正如 this boost article 所讨论的那样。

它大部分都可以工作,除了有时,当我启动并且共享内存段已经存在时,managed_shared_memory::find 会挂起。

调试器显示它卡在 boost::interprocess 内部的某个进程间互斥体上。

我已经检查过了,我没有其他进程会挂在这个共享内存上。

如果按照我的代码进行测试,则测试开始,如果发现该段已存在,则调用 destroyMyShm()。 destroyMyShm() 打开该段并尝试在应该位于该段内的向量上调用 managed_shared_memory::find() 。此查找挂起。

请注意,如果我只是调用 shared_memory_object::remove() 一切正常。我不知道这是否会导致泄漏,因为矢量不会被正确销毁。

对此我有什么办法吗?可能是 boost 中的错误?

只调用 shared_memory_object::remove() 并忘记 managed_shared_memory::destroy() 是否安全?

#include <gtest/gtest.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>

typedef  boost::interprocess::allocator<std::string, boost::interprocess::managed_shared_memory::segment_manager>  ShmemAllocator;
typedef  boost::interprocess::vector<std::string, ShmemAllocator> MyVector;


static const char *kSharedMemorySegmentName("myseg");
static const char *kSharedMemoryVectorName("myvec");

bool isMyShmCreated();
void  destroyMyShm();
void initMyShm(size_t);

//pardon my google-test method here...
TEST(MyTest, SharedMemoryTest) 
    using namespace boost::interprocess;
    if (isMyShmCreated())
    
        destroyMyShm();  //hangs in here (see below)
    
    EXPECT_FALSE(isMyShmCreated());
    initMyShm(1000000);
    EXPECT_TRUE(isMyShmCreated());


    managed_shared_memory segment(open_only, kSharedMemorySegmentName);
    MyVector *vec = segment.find<MyVector>(kSharedMemoryVectorName).first;

    EXPECT_TRUE(vec != 0);
    vec->push_back(std::string("item 1"));
    vec->push_back(std::string("item 2"));


   destroyMyShm();



void initMyShm(size_t size) 
    using namespace boost::interprocess;
    if (isMyShmCreated()) 
        log("already created");
    
    managed_shared_memory segment(open_or_create, kSharedMemorySegmentName, size);
    MyVector *vec = segment.find<MyVector>(kSharedMemoryVectorName).first;
    if (!vec)
    
        const ShmemAllocator alloc_inst (segment.get_segment_manager());
        segment.construct<MyVector>(kSharedMemoryVectorName)(alloc_inst);
     else
    
        vec->clear();
    


bool isMyShmCreated()

    using namespace boost::interprocess;
    try
    
        managed_shared_memory segment(open_only, kSharedMemorySegmentName);
        return segment.check_sanity();
     catch (const interprocess_exception &ex) 
        std::cout << "managed_shared_memory ex: "  << ex.what();
    
    catch (const std::exception &ex) 
        std::cout << "managed_shared_memory ex: "  << ex.what();
    
    catch (const std::string& ex)
    
        std::cout << "managed_shared_memory ex: "  << ex;
     catch (...)
    
        std::cout << "managed_shared_memory ex: ?";
    
    return false;


void destroyMyShm() 
    using namespace boost::interprocess;
    try
    
        managed_shared_memory segment(open_only, kSharedMemorySegmentName);
        // hangs on segment.find() below:
        if (segment.find<MyVector>(kSharedMemoryVectorName).first)  
            segment.destroy<MyVector>(kSharedMemoryVectorName);
     catch (...) 
    try
    
        shared_memory_object::remove(kSharedMemorySegmentName);
     catch (...) 

【问题讨论】:

【参考方案1】:

您不应该使用basic_string&lt;char, ShmemAllocator&gt; 而不是string 吗?你的向量实际上是容器的容器——我认为都应该使用共享分配器。 (你需要两个,一个用于字符串 - 字符 - 第二个用于向量 - 你的特殊字符串)

编辑:在提升页面的末尾有一个名为“Container of Containers”的链接……阅读! (我只是在猜测,那一页证明我是对的。)

链接:Boost: Creating vectors in shared memoryBoost: Containers of containers

【讨论】:

以上是关于boost::interprocess 共享内存段函数 find() 如果段已经存在,则在启动时挂起的主要内容,如果未能解决你的问题,请参考以下文章

boost::interprocess 32 位和 64 位进程之间的共享内存

boost::interprocess::named_mutex 是不是需要存储在共享内存中?

boost::interprocess 不在共享内存副本中的容器容器

boost中的异常:进程间,共享内存对象删除

使用 Boost.Interprocess 使进程等待直到资源加载到共享内存中

Boost.Interprocess内存位置