首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >增长managed_shared_memory数据段后出现分段故障

增长managed_shared_memory数据段后出现分段故障
EN

Stack Overflow用户
提问于 2019-09-13 04:17:58
回答 1查看 302关注 0票数 1

我正在尝试boost库的共享内存部分,为一个更大的项目做准备。我需要一个共享内存段,在初始化时我不一定知道它的大小,所以我的计划是增加这个段。

我的初始实现在共享内存中存储了一个boost::interprocess::vector。当我向向量添加值时,如果向量的大小超出了段的大小(抛出bad_alloc异常),则增加段的大小。这通常会工作几次,直到我得到一个分段错误。

不确定这是否有帮助,在这个实现之前,我的代码会在调用managed_shared_memory::grow()方法时挂起。经过一些谷歌搜索后,我发现这很可能是因为片段仍然映射到主进程。当前错误发生在我将remover结构移出构造函数之后。现在,代码不会挂起,但它确实有segfault。

代码如下:

代码语言:javascript
复制
#include <iostream>
#include <exception>

#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>

using namespace boost::interprocess;

static const std::string SHMEM_NAME = "MySharedMemorySegment";

typedef allocator<int, managed_shared_memory::segment_manager> IntAllocator;
typedef vector<int, IntAllocator> ShmemVector;

class ShmemTest {
private:
    managed_shared_memory *segment;
    const IntAllocator *allocator_instance;
    ShmemVector *test_vector;
    size_t shmem_block = 10000;  // Originally, I could allocate 65536 without problems
    struct shm_remove {
        shm_remove()  { shared_memory_object::remove(SHMEM_NAME.data()); }
        ~shm_remove() { shared_memory_object::remove(SHMEM_NAME.data()); }
    } remover;

public:
    ShmemTest() {
        segment = new managed_shared_memory(create_only, SHMEM_NAME.data(), shmem_block);
        allocator_instance = new IntAllocator(segment->get_segment_manager());
    }

    void create_vector() {
        test_vector = segment->construct<ShmemVector>("ShmemVector")(*allocator_instance);
    }

    void append(int value) {
        try {
            test_vector->push_back(value);
        } catch (std::exception & e) {  // Grow shared memory if out of memory
            std::cout << e.what() << std::endl;
            std::cout << "Growing the shared memory block" << std::endl;
            managed_shared_memory::grow(SHMEM_NAME.data(), 1000);
            std::cout << "Done growing the shared memory block, current size: " << size();
            std::cout << " max size: " << max_size() << std::endl;
            test_vector->push_back(value);
            std::cout << "Added value after growing shared memory block" << std::endl;
        }
    }

    void print() {
        std::cout << "ShmemVector values: ";
        for (int value : *test_vector) {
            std::cout << " " << value << " ";
        }
        std::cout << std::endl;
    }

    size_t max_size() {
        return test_vector->max_size();
    }

    size_t size() {
        return test_vector->size();
    }

    void destroy() {
        segment->destroy<ShmemVector>("ShmemVector");
    }
};

int main() {
    ShmemTest shmem_test;
    shmem_test.create_vector();
    std::cout << "Max size: " << shmem_test.max_size() << std::endl;
    for (int i = 0; i < 16380; ++i) {
        shmem_test.append(i);
        if (i > 16200) {
            std::cout << "Current size: " << shmem_test.size() << " ";
        }
    }
    std::cout << std::endl;
    shmem_test.print();
    shmem_test.destroy();
}

这是我得到的典型输出:

代码语言:javascript
复制
Max size: 2496
boost::interprocess::bad_alloc
Growing the shared memory block
Done growing the shared memory block, current size: 2414 max size: 2746
Added value after growing shared memory block
boost::interprocess::bad_alloc
Growing the shared memory block
Done growing the shared memory block, current size: 2662 max size: 2996
Added value after growing shared memory block
boost::interprocess::bad_alloc
Growing the shared memory block
Done growing the shared memory block, current size: 2914 max size: 3246
Segmentation fault (core dumped)

解决方案

正如oxuf所指出的,重新映射数据段,然后使用find是可行的。下面是更新后的函数,以防有人遇到同样的问题:

代码语言:javascript
复制
void append(int value) {
    try {
        test_vector->push_back(value);
    } catch (std::exception & e) {  // Grow shared memory if out of memory
        managed_shared_memory::grow(SHMEM_NAME.data(), 1000);
        // Re-map the shared memory segment
        segment = new managed_shared_memory(open_only, SHMEM_NAME.data());
        // Find the vector object in the newly mapped shared memory segment
        std::pair<ShmemVector*, size_t> return_value = segment->find<ShmemVector>("ShmemVector");
        test_vector = return_value.first;
        // Append the value
        test_vector->push_back(value);
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-13 06:58:54

每次段增长时,操作系统可以自由地重新分配整个内存块,然后,指向该内存的所有指针都无效。然后,test_vector可以在增长后指向无效内存。再次尝试映射该段,这次使用open_only选项,并使用managed_shared_memory::find连接到您的vector

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57913960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档