提升 IPC 字符串长度段错误
boost IPC string length segfault?
我有一个非常小的两个程序的例子,一个用于编写共享内存段,另一个用于从中读取。我意识到std::string
(和其他容器)可能存在问题,因此尝试了boost::interprocess::string
这是一个boost::containers::string
。 我很确定这缺少一些真正基本和简单的东西,但看不到它!
无论如何,概要是,当字符串很小(我认为虽然比 SSO 大)时,运行第一个程序会写入内存,第二个程序读取得很好。但是,如果我像这里的例子一样使字符串非常大,那么读取程序就会出现段错误。如果读取和写入都在同一个过程中,但功能不同,我就成功了(因此除了通过 ipc 之外不共享任何数据。下面的代码writeipc.cc
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <iostream>
#include <utility>
int main()
{
typedef boost::interprocess::string bi_string;
boost::interprocess::shared_memory_object::remove("Test");
boost::interprocess::managed_shared_memory managed_shm(boost::interprocess::create_only, "Test", 65536);
bi_string* i = managed_shm.construct<bi_string>("string")("abcdefghijklmnopqrstuvwxyzaskl;dfjaskldfjasldfjasdl;fkjwrotijuergonmdlkfsvmljjjjjjjjjjjjjj"); // make smaller (ie "jjjjjjjjjjjjjj" and test passes
std::cout << "inserting into shm" << *i << std::endl;
std::pair<bi_string*, size_t> q = managed_shm.find<bi_string>("string");
std::cout << *q.first << std::endl;
while(true)
std::cout << "still running"; // hack to keep process running (not required)
}
readipc.cc
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <iostream>
int main()
{
typedef boost::interprocess::string bi_string;
boost::interprocess::managed_shared_memory managed_shm(boost::interprocess::open_only, "Test");
std::pair<bi_string*, std::size_t> p = managed_shm.find<bi_string>("string");
std::cout << "existing value" << *p.first << std::endl;
}
好的,答案与分配器有关。
我正在发布我认为是答案的内容,以便其他人快速了解如何开始使用IPC。我发现许多关于网络的例子不能很好地解释这个过程,给人的印象是使用普通字符串等就可以了,直到你从不同的过程中阅读。因此,要完全实施解决方案,需要一些额外的小步骤。
实质上,您不能使用普通 stl 类型容器提供的分配器。此处记录了此文档
这是在哪里分配的?
Boost.进程间容器放置在共享内存/内存中 映射文件等...同时使用两种机制:
Boost.Interprocess construct<>, find_or_construct<>... functions. These functions place a C++ object in the shared memory/memory mapped
文件。但这只放置了对象,而不是内存 对象可以动态分配。 共享内存分配器。这些允许分配共享内存/内存映射文件部分,以便容器可以分配 用于存储新插入元素的动态内存片段。
这意味着要放置任何 Boost.Interprocess 容器(包括 Boost.Interprocess strings)在共享内存或内存映射文件中, 容器必须:
Define their template allocator parameter to a Boost.Interprocess allocator. Every container constructor must take the Boost.Interprocess allocator as parameter. You must use construct<>/find_or_construct<>... functions to place the container in the managed memory.
如果您执行了前两点,但没有使用构造<>或 find_or_construct<>创建仅放置在 进程,但为共享的包含类型分配内存 内存/内存映射文件。
我创建了几个示例函数,可以在这里找到
上面缺少的是
namespace bi = boost::interprocess;
typedef bi::allocator<char, bi::managed_shared_memory::segment_manager> CharAllocator;
typedef bi::basic_string<char, std::char_traits<char>, CharAllocator> bi_string;
现在这是一个字符串,当我们可以为它获取分配器时可以存储它。这意味着像这样从内存段获取分配器
bi::managed_shared_memory segment(bi::create_only, "shm name",
65536);
// Create an object of Type initialized to type
CharAllocator charallocator(segment.get_segment_manager());
现在,Charallocator 可用于构造一个字符串类型,该类型将在共享内存位置工作并能够正确读回。字符串的创建方式为:
bi_string str(charallocator);
然后,您可以为此分配一个字符串。例如std::string test("a test string");
str = test.c_str();
如果你构造一个段,你的字符串将被存储
segment.construct<bi_string>("some name")(str)
您可以在共享内存存储中存储多个段。我希望这对其他人有所帮助。上面的链接中提供了所有代码。
- 为什么PyImport_ImportModule python 3.7.2 中出现段错误?
- 为什么在访问 vtkRenderWindow 的"交互器"变量时会发生段错误?
- 全局向量导致 C++ 程序结束时出现段错误
- 为什么重载运算符<<打印特征类成员会导致段错误?
- 更改条件段错误
- 使用 TTF_RenderText() 加载字体时获取段错误 TTF_OpenFontRW()
- 注册对对象工厂的调用会导致段错误
- pthread_create在构造函数段错误中
- Nanoflann发现邻居提出段错误
- C++ 中的构造函数、继承、堆栈、堆、this-pointer 和段错误
- 具有unique_ptr的 CRTP 会导致段错误
- 增强纤维work_stealing屏障会导致段错误
- 当我返回指向结构的指针向量时出现段错误
- C++为什么我的代码没有爆炸/段错误?
- Pthread段错误,使用指向main中变量的指针
- C++ 模板中的段错误
- 相当于Windows/MSVC上的段错误?
- 为什么我的 LLVM JIT 实现出现段错误?
- 为什么访问我的引用捕获变量会导致我的 lambda 函数出现段错误?
- 为什么自删除的全局 Vulkan 实例仅在添加层时才导致段错误?