尝试访问内部地图时程序崩溃

时间:2014-10-21 20:11:30

标签: c++ boost stl

以下是一个小型的读者作家计划。作者将值写入地图地图,写入成功。  还有一个名为reader的进程读取SHM的内容,读者在读取外部映射的键时没有问题,但是如果我们尝试访问内部映射的内容则会崩溃。   我检查了容器大小,它为case1打印2,这很好,因为内部地图包含2个关键字“case1”的元素。

然而,当我尝试访问内部地图程序崩溃时,我访问内部地图的方式不正确。以下是我正在使用的代码片段。

ShmTypedefs.h

#ifndef __SHM_TYPE_DEFS__
    #define __SHM_TYPE_DEFS__
    #include <boost/interprocess/allocators/allocator.hpp>
    #include <boost/interprocess/managed_shared_memory.hpp>
    #include <boost/interprocess/containers/string.hpp>
    #include <boost/interprocess/containers/map.hpp>

    //the strings also need to be assigned from the shared memory
    typedef boost::interprocess::allocator<void, boost::interprocess::managed_shared_memory::segment_manager> VoidAllocator;
    typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> CharAllocator;
    typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> SharedString;

    //Note that map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>,
    //so the allocator must allocate that pair.
    typedef SharedString KeyType;
    typedef boost::interprocess::map<SharedString, int>  MappedType;
    typedef std::pair<const KeyType, MappedType> ValueType;

    //allocator for the string
    typedef boost::interprocess::allocator<SharedString, boost::interprocess::managed_shared_memory::segment_manager> StringAllocator;
    //allocator of for the map.
    typedef boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator;
    typedef boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator;
    //third parameter argument is the ordering function is used to compare the keys.
    typedef boost::interprocess::map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> MySHMMap;
#endif

writer.cxx

    #include <boost/interprocess/containers/map.hpp>
    #include <functional>
    #include <utility>
    #include <ShmTypedefs.h>
    #include <iostream>
    using namespace boost::interprocess;

    int main ()
    {
      // remove earlier existing SHM
      shared_memory_object::remove("SharedMemoryName");

      // create new
      managed_shared_memory segment(create_only,"SharedMemoryName",65536);

      //Initialize the shared memory STL-compatible allocator
      ShmemAllocator alloc_inst (segment.get_segment_manager());

      //third parameter argument is the ordering function is used to compare the keys.
      typedef map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> MySHMMap;

      //offset ptr within SHM for map
      //After construction m_pmap will contain the only object that has been consturcted in pmap[0]
      //If we construct another object it will goto pmap[1]

      offset_ptr<MySHMMap> m_pmap = segment.construct<MySHMMap>("MySHMMapName")(std::less<SharedString>(), alloc_inst);

      //Insert data in the map
      StringAllocator string_alloc_instance( segment.get_segment_manager() );

      SharedString key("case1", string_alloc_instance );
      SharedString inner_map_key("inner_case1", string_alloc_instance );

      SharedString key1("case2", string_alloc_instance );
      SharedString inner_map_key1("inner_case2", string_alloc_instance );

      SharedString inner_map_key2("inner_case3", string_alloc_instance );

      m_pmap[0][key][inner_map_key] = 2030;
      m_pmap[0][key1][inner_map_key1] = 2031;
      m_pmap[0][key][inner_map_key2] = 2034;
      std::cout<<"\n "<<m_pmap[0][key][inner_map_key]<< std::endl;
      std::cout<<"\n "<<m_pmap[0][key1][inner_map_key1]<< std::endl;
      return 0;
    }

reader.cxx

 #include <boost/interprocess/containers/map.hpp>
#include <functional>
#include <utility>
#include <iostream>
#include <ShmTypedefs.h>

using namespace boost::interprocess;

int main ()
{

  try
  {

    managed_shared_memory segment(open_or_create, "SharedMemoryName",65536);

    int size= segment.find<MySHMMap>("MySHMMapName").second;
    std::cout<< "size of map " << size << std::endl;
    offset_ptr<MySHMMap> m_pmap = segment.find<MySHMMap>("MySHMMapName").first;
    MySHMMap :: iterator iter = m_pmap[0].begin();
    MySHMMap :: iterator iter_end = m_pmap[0].end();
    for(; iter != iter_end; ++iter ) {
      std::cout<<"\n "<< iter->first<<std::endl;
      if( iter->first == "case1" ) {
         MappedType::iterator iti = (iter->second).begin();

         MappedType::iterator iti_end = (iter->second).end();
         for( ;iti != iti_end; ++iti ) {
         std::cout << "symbol " << iti->first << " time " << iti->second << std::endl;
          }
      }
    }
  }
  catch(std::exception &e) {
    std::cout<<" error  " << e.what() <<std::endl;
    shared_memory_object::remove("SharedMemoryName");
  }
  return 0;
}

堆栈追踪:

运行程序时的输出=&gt;

   droy@apdeva01 shmmapofmap> ./bin/reader
    size of map 1
    case1
    Matched case 1
    Size of the inner container is 2 units
    Segmentation fault (core dumped)

核心输出:

(gdb) bt
#0  get_right () at /home/dev/build/third_party/64-rhel5/boost_1_47_0/include/boost/intrusive/detail/rbtree_node.hpp:130
#1  next_node () at /home/dev/build/third_party/64-rhel5/boost_1_47_0/include/boost/intrusive/detail/tree_algorithms.hpp:441
#2  next_node () at /home/dev/build/third_party/64-rhel5/boost_1_47_0/include/boost/intrusive/rbtree_algorithms.hpp:353
#3  operator++ () at /home/dev/build/third_party/64-rhel5/boost_1_47_0/include/boost/intrusive/detail/tree_node.hpp:119
#4  prot_incr ()
    at /home/dev/build/third_party/64-rhel5/boost_1_47_0/include/boost/interprocess/containers/container/detail/tree.hpp:326
#5  operator++ ()
    at /home/dev/build/third_party/64-rhel5/boost_1_47_0/include/boost/interprocess/containers/container/detail/tree.hpp:395
#6  __distance<boost::container::containers_detail::rbtree<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > >, std::pair<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > const, int>, boost::container::containers_detail::select1st<std::pair<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > const, int> >, std::less<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > >, std::allocator<std::pair<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > const, int> > >::iterator> ()
    at /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_iterator_base_funcs.h:79
#7  distance<boost::container::containers_detail::rbtree<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interproce---Type <return> to continue, or q <return> to quit---
ss::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > >, std::pair<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > const, int>, boost::container::containers_detail::select1st<std::pair<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > const, int> >, std::less<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > >, std::allocator<std::pair<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > const, int> > >::iterator> ()
    at /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_iterator_base_funcs.h:114
#8  main () at /home/user/droy/src/quotes/debshmutils/shmmapofmap/src/reader.cxx:33

1 个答案:

答案 0 :(得分:1)

您的映射类型:

typedef boost::interprocess::map<SharedString, int>  MappedType;

不会在共享内存中分配其节点。因此,外部映射中的指针指向本地堆上的地址,因此在读取端不存在(或未定义)。

以下是固定作家 Live On Coliru 。相关的typedef:

typedef boost::interprocess::allocator<std::pair<const SharedString, int>, boost::interprocess::managed_shared_memory::segment_manager > InnerMapAlloc;
typedef boost::interprocess::map<SharedString, int, std::less<SharedString>, InnerMapAlloc>  MappedType;

输出:

case1, inner_case1, 2030
case1, inner_case2, 2031
case1, inner_case3, 2034

注意:

  • 你在主
  • 中有一个冲突的MySHMMap定义
  • 这是非常笨拙的代码。

    InnerMapAlloc inner_map_alloc_instance(segment.get_segment_manager());
    
    {
        MappedType& tmp = m_pmap->emplace(key, MappedType(inner_map_alloc_instance)).first->second;
        tmp.emplace(inner_map_key, 2030);
        tmp.emplace(inner_map_key2, 2034);
    }
    
    {
        MappedType& tmp = m_pmap->emplace(key, MappedType(inner_map_alloc_instance)).first->second;
        tmp.emplace(inner_map_key1, 2031);
    }
    
    for (auto const& outer : *m_pmap)
        for (auto const& inner : outer.second)
            std::cout << outer.first << ", " << inner.first << ", " << inner.second << "\n";
    

    考虑疯狂地简化数据结构和/或在隐藏uglies的适当类中将其抽象出来

    更新发布了PoC based on Boost MultiIndex

  • 据我所知,

    // After construction m_pmap will contain the only object that has been constructed in pmap[0]
    // If we construct another object it will goto pmap[1]
    

    我从未听说过这个。你能指出陈述这一点的文件吗?