首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >提升IPC字符串长度分段故障?

提升IPC字符串长度分段故障?
EN

Stack Overflow用户
提问于 2013-10-23 09:50:50
回答 1查看 512关注 0票数 1

我有一个很小的两个程序的例子,一个用于编写共享内存段,另一个用于从中读取。我意识到std::string (和其他容器)可能存在问题,所以已经尝试了boost::interprocess::string,也就是boost::containers::string。我很确定这是缺少一些真正的基本和简单的东西,但看不到它!

在任何情况下,概要都是,当字符串很小(我认为比SSO大),运行第一个程序时,第一个程序写入内存,第二个程序读得非常好。但是,如果我使字符串非常大,就像这里的示例一样,那么读取程序分段错误。如果读写过程相同,但功能不同(因此,除了通过ipc共享任何数据),我在这方面取得了成功。writeipc.cc下面的代码

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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; 

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-24 16:19:47

好的,答案是分配器相关的。

我正在发布我相信的答案,以便让其他人快速了解如何开始使用IPC。我已经找到了很多关于网络的例子,它们不能很好地解释这个过程,并且给人的印象是使用普通的字符串等会很好,直到你从一个不同的过程中读到。因此,要完全实现解决方案,需要一些小的额外步骤。

本质上,您不能使用普通stl类型容器提供的分配器。这是记录在案的这里

这是在哪里分配的? Boost.Interprocess容器放置在共享内存/内存映射文件中,等等.同时使用两种机制: Boost.Interprocess construct<>,find_or_construct<>.函数。这些函数将C++对象放置在映射的共享内存/内存中。 文件。但是这只会放置对象,而不是这个对象可以动态分配的内存。共享内存分配器。这些允许分配共享内存/内存映射文件部分,以便容器能够动态地分配内存片段来存储新插入的元素。 这意味着要将任何Boost.Interprocess容器(包括Boost.Interprocess字符串)放置在共享内存或内存映射文件中,容器必须: 将其模板分配器参数定义为Boost.Interprocess分配器。每个容器构造函数都必须以Boost.Interprocess分配器作为参数。您必须使用构造<>/find_or_construct<>.函数将容器放置在托管内存中。 如果执行前两点,但不使用construct<>或find_or_construct<>,则将创建一个只放置在流程中的容器,但该容器将从共享内存/内存映射文件中为包含的类型分配内存。

我创建了几个示例函数,可以找到这里

上面缺少的是

代码语言:javascript
复制
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;

这现在是一个字符串,当我们可以为它获得一个分配器时,它可以被存储。这意味着从内存段中获取分配器,如下所示

代码语言:javascript
复制
  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可以用来构造一个字符串类型,该字符串类型将在共享内存位置工作,并且能够正确地读取。该字符串创建为:

代码语言:javascript
复制
 bi_string str(charallocator);

然后,您可以为它分配一个cstring。例如std::string test("a test string");

代码语言:javascript
复制
str = test.c_str();

如果构造一个段,则将存储字符串。

代码语言:javascript
复制
segment.construct<bi_string>("some name")(str)

您可以在共享内存存储中存储许多段。我希望这对其他人有帮助。在上面的链接中,所有的测试都是可用的。

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

https://stackoverflow.com/questions/19538368

复制
相关文章

相似问题

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