Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
242 views
in Technique[技术] by (71.8m points)

c++ - Program crashes when trying to access the inner map

Following is a small reader writer program. The writer writes values to a map of maps, the write is successful. There is another process called reader which reads the contents of the SHM, the reader has no problem in reading the key of the outer map, however if we try to access the contents of the inner map it crashes. I have checked the container size and it prints 2 for case1 which is fine as the inner map contains 2 elements for the key "case1".

However, when I try to access to inner map the program crashes, is the way I am accessing the inner map not correct. Following are the code snippets that I am using.

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<<"
 "<<m_pmap[0][key][inner_map_key]<< std::endl;
      std::cout<<"
 "<<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<<"
 "<< 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;
}

Stack Trace:

Output when I run the program =>

   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)

Core output:

(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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your mapped type:

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

does not allocate its nodes in shared memory. Therefore, the pointers in the outer map are pointing to addresses on the local heap and hence do not exist (or are undefined) on the reading side.

Here is the fixed writer Live On Coliru. Relevant typedefs:

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;

Outputs:

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

Note:

  • you had a conflicting MySHMMap definition inside main
  • this is very clumsy code.

    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 << "
    ";
    

    Consider wildly simplifying the datastructure and/or abstracting it away in a proper class hiding the uglies

    UPDATE Posted a PoC based on Boost MultiIndex

  • As far as I can tell,

    // 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]
    

    I had never heard of this. Can you point to the documentation where this is stated?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...