linux 在共享内存中存储std::vector

kmpatx3s  于 2023-08-03  发布在  Linux
关注(0)|答案(1)|浏览(192)

我试图通过将std::vector存储在共享内存中来在两个进程之间共享它。第一个进程尝试向向量添加一些数据,第二个进程尝试读取数据。
为了创建向量,我使用类似于以下内容:

offset_t offset = custom_malloc(sizeof(std::vector<char, CustomAllocator<char>>));

uint8_t *ptr = shared_memory_base_ptr + offset;

std::vector<char, CustomAllocator<char>> *shared_vector = new (ptr) std::vector<char, CustomAllocator<char>>();
shared_vector->push_back('S');
shared_vector->push_back('h');
shared_vector->push_back('a');

字符串
要从第二个进程读取向量,我使用以下命令:

const uint8_t *ptr = shared_memory_base_ptr + offset;

const std::vector<char, CustomAllocator<char>> *shared_vector = reinterpret_cast<const std::vector<char, CustomAllocator<char>> *>(ptr);
std::cout << shared_vector->size() << std::endl;  // 3
std::cout << shared_vector->at(0) << std::endl;  // Segfault


问题是,当试图使用vector->at(i)访问任何向量位置时,由于无效的内存地址,我会得到一个分段错误。
我尝试使用&(vector->at(i))打印向量中元素的地址,看起来它是与创建向量的第一个进程对应的虚拟地址,这可能是第二个进程的无效地址。
有什么办法可以克服吗?第二个进程如何知道向量元素的正确地址?
编辑:为了完整起见,我还提供了用于vector的自定义分配器的示例代码:

template <typename T>
class CustomAllocator
{
public:
    using value_type = T;

    CustomAllocator() noexcept {}

    T *allocate(std::size_t n) {
        const offset_t offset = custom_malloc(n * sizeof(T));
        return reinterpret_cast<T *>(shared_memory_base_ptr + offset);
    }

    void deallocate(void *p, std::size_t n) {
        (void)n;
        if (p) {
            const offset_t offset = static_cast<uint8_t *>(p) - shared_memory_base_ptr);
            custom_free(offset);
        }
    }
};


我知道向量本身包含指向其底层结构的指针,这些指针在单独的进程中无效,除非共享内存Map到与@Dmitry在注解中指出的相同的虚拟地址。

wfsdck30

wfsdck301#

vector不仅仅是它保存的数据,它还是一个指向存储数据的堆分配内存的指针。因此,当你把向量放到你的小共享内存中时,你用placement-new放置的只是一堆内务数据和指向实际数据的指针。毕竟,sizeof是一个编译时常量,你难道一点也不好奇为什么它能在像vector这样的动态对象上工作吗?
至于指针,指针只在应用程序的地址空间中有效,它甚至不能跨同一机器上的不同应用程序移植。这个解决方案对IPC来说是不可行的,你必须设计一个不同的解决方案。

相关问题