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