title: c++ Boost interprocess shared_ptr exception
body: <p>I am trying to save a shared pointer (boost interprocess) in an interprocess unordered map as the value. In my test program, I am inserting about 100 elements. Each element has a string as the key and a shared_ptr as the value. The shared_ptr is a pointer to a complex data type.</p>
  
  <p>The creation and insertion for the 1st element completes successfully. However, I get an exception when I am creating the shared_ptr instance for the second element. I am getting the following exception:</p>
  
  <p>error: boost::interprocess_exception::library_error.
  error-code: Bad file descriptor.
  native-error: 0.</p>
  
  <p>I've pasted the code below. Any help is appreciated. Thanks.</p>
  
  <p>defs.h</p>
  
  <pre><code>// basic shared memory defs.
  #pragma once
  
  #include &lt;boost/interprocess/managed_shared_memory.hpp&gt;
  #include &lt;boost/interprocess/allocators/allocator.hpp&gt;
  #include &lt;boost/interprocess/containers/string.hpp&gt;
  
  namespace bip = boost::interprocess;
  
  namespace ip {
  
  namespace shmem {
  
    using segment = bip::managed_shared_memory;
    using segment_manager = segment::segment_manager;
  
    using void_allocator = bip::allocator&lt;void, segment_manager&gt;;
    using char_allocator = bip::allocator&lt;char, segment_manager&gt;;
    using int_allocator = bip::allocator&lt;int, segment_manager&gt;;
    using double_allocator = bip::allocator&lt;double, segment_manager&gt;;
    using size_t_allocator = bip::allocator&lt;size_t, segment_manager&gt;;
    using string = bip::basic_string&lt;char, std::char_traits&lt;char&gt;, char_allocator&gt;;
  
  } // namespace shmem
  
  } // namespace ip
  </code></pre>
  
  <p>map-value.h</p>
  
  <pre><code>#pragma once
  #include &lt;boost/interprocess/smart_ptr/deleter.hpp&gt;
  #include &lt;boost/interprocess/smart_ptr/shared_ptr.hpp&gt;
  #include &lt;cassert&gt;
  
  #include "defs.h"
  
  namespace ip
  {
  
  template &lt;typename ValueType&gt;
  class MapValue
  {
  public:
    using MVType = MapValue&lt;ValueType&gt;;
    typedef typename bip::deleter&lt;MVType, shmem::segment_manager&gt; MVDeleter;
    typedef typename bip::managed_shared_ptr&lt;MVType, shmem::segment&gt;::type MapValuePtr;
  
    MapValue(const shmem::void_allocator&amp;, ValueType value=ValueType(), size_t=0);
  
    MapValue(const MapValue&amp; other);
    MapValue&amp; operator=(const MapValue&amp; other);
    MapValue(const MapValue&amp;&amp; other) noexcept;
    MapValue&amp; operator=(const MapValue&amp;&amp; other) noexcept;
    void swap(const MapValue&amp; other) noexcept;
  
    size_t GetTimestamp() const { return mTimestamp; }
    ValueType GetValue() const { return mValue; }
  
  private:
    size_t mTimestamp;
    ValueType mValue;
  };
  
  } // namespace ip
  </code></pre>
  
  <p>map-value.cc</p>
  
  <pre><code>#include "map-value.h"
  
  namespace ip
  {
  
  template &lt;typename ValueType&gt;
  MapValue&lt;ValueType&gt;::MapValue(const shmem::void_allocator &amp;void_allocator
                                            , ValueType value, size_t expire_ts)
  : mTimestamp(expire_ts)
  , mValue(value, void_allocator)
  {
  }
  
  template &lt;typename ValueType&gt;
  MapValue&lt;ValueType&gt;::MapValue(const MapValue&amp; other)
  : mTimestamp(other.mTimestamp)
  , mValue(other.mValue)
  {
  }
  
  template &lt;typename ValueType&gt;
  MapValue&lt;ValueType&gt;&amp;
  MapValue&lt;ValueType&gt;::operator=(const MapValue&amp; other)
  {
    MapValue tmp(other);
    swap(tmp);
    return *this;
  }
  
  template &lt;typename ValueType&gt;
  MapValue&lt;ValueType&gt;::MapValue(const MapValue&amp;&amp; other) noexcept
  : mTimestamp(std::move(other.mTimestamp))
  , mValue(std::move(other.mValue))
  {
  }
  
  template &lt;typename ValueType&gt;
  MapValue&lt;ValueType&gt;&amp;
  MapValue&lt;ValueType&gt;::operator=(const MapValue&amp;&amp; other) noexcept
  {
    auto tmp = std::move(other);
    swap(tmp);
    return *this;
  }
  
  template &lt;typename ValueType&gt;
  void
  MapValue&lt;ValueType&gt;::swap(const MapValue&amp; other) noexcept
  {
    mTimestamp = other.mTimestamp;
    mValue = other.mValue;
  }
  
  template class MapValue&lt;shmem::string&gt;;
  
  } // namespace ip
  </code></pre>
  
  <p>unorderd_map_master.cc</p>
  
  <pre><code>#include &lt;chrono&gt;
  #include &lt;cstdlib&gt;
  #include &lt;iostream&gt;
  #include &lt;functional&gt;                 //std::equal_to
  #include &lt;sstream&gt;
  #include &lt;string.h&gt;
  
  #include &lt;boost/interprocess/managed_shared_memory.hpp&gt;
  #include &lt;boost/interprocess/allocators/allocator.hpp&gt;
  #include &lt;boost/unordered_map.hpp&gt;    //boost::unordered_map
  #include &lt;boost/functional/hash.hpp&gt;  //boost::hash
  
  #include "map-value.h"
  
  using namespace boost::interprocess;
  using namespace ip;
  
  int
  main ()
  {
    shared_memory_object::remove("MySharedMemory");
  
    // Create shared memory
    managed_shared_memory segment(create_only, "MySharedMemory", 1024*64);
  
    // Note that unordered_map&lt;Key, MappedType&gt;'s value_type is 
    // std::pair&lt;const Key, MappedType&gt;, so the allocator must allocate a pair.
    // 
    typedef int  KeyType;
    //typedef size_t  MappedType;
    typedef std::pair&lt;const int, MapValue&lt;shmem::string&gt;::MapValuePtr&gt; ValueType;
  
    // Typedef the allocator
    typedef allocator&lt;ValueType, shmem::segment_manager&gt; ShmemAllocator;
  
    // Alias an unordered_map of ints that uses the previous STL-like allocator.
    typedef boost::unordered_map&lt;KeyType, MapValue&lt;shmem::string&gt;::MapValuePtr
                                 , boost::hash&lt;KeyType&gt;, std::equal_to&lt;KeyType&gt;
                                 , ShmemAllocator&gt; SharedHashMap;
  
    // Construct a shared memory hash map.
    // Note that the first parameter is the initial bucket count and
    // after that, the hash function, the equality function and the allocator
    SharedHashMap *hashmap = segment.construct&lt;SharedHashMap&gt;("SharedHashMap")      //object name
                                 (4                                       // bucket count
                                  , boost::hash&lt;KeyType&gt;()                // hash func
                                  , std::equal_to&lt;KeyType&gt;()              // equality func
                                  , segment.get_allocator&lt;ValueType&gt;());  //allocator instance
  
    int i;
    std::string test("test");
  
    using MVString = MapValue&lt;shmem::string&gt;;
    using MVStringPtr = MVString::MapValuePtr;
    using MVStringDeleter = MVString::MVDeleter;
    shmem::void_allocator alloc_inst (segment.get_segment_manager());
  
    try {
      // Insert data in the hash map
      for (i = 0; i &lt; 100; ++i) {
        // Create a shared pointer in shared memory
        // pointing to a newly created object in the segment
        std::ostringstream ostr;
        ostr &lt;&lt; test &lt;&lt; i;
        const uint64_t now = std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(
                                    std::chrono::steady_clock::now().time_since_epoch()).count();
        size_t ts = now + 60*1000000;   // 60s from now.
  
        shmem::string name(ostr.str().c_str(), alloc_inst);
        std::cout &lt;&lt; "created name: " &lt;&lt; name &lt;&lt; '\n';
        MVStringPtr sh_ptr_instance =
            make_managed_shared_ptr(segment.construct&lt;MVString&gt;("MVString")(alloc_inst
                                                                            , name, ts), segment);
  
        assert(sh_ptr_instance.use_count() == 1);
        std::cout &lt;&lt; "created shared_ptr" &lt;&lt; '\n';
  
        hashmap-&gt;insert(ValueType(i, sh_ptr_instance));
        std::cout &lt;&lt; "Inserting at " &lt;&lt; i &lt;&lt; ": "
                  &lt;&lt; "value: " &lt;&lt; ostr.str() &lt;&lt; ". "
                  &lt;&lt; "timestamp: " &lt;&lt; ts &lt;&lt; '\n';
      }
    }
    catch (const bip::interprocess_exception&amp; e) {
      std::cout &lt;&lt; "error: " &lt;&lt; e.what() &lt;&lt; ". "
                &lt;&lt; "error-code: " &lt;&lt; strerror(e.get_error_code()) &lt;&lt; ". "
                &lt;&lt; "error-msg: " &lt;&lt; e.get_native_error() &lt;&lt; ". " &lt;&lt; '\n';
      std::cout &lt;&lt; "Error while inserting element #" &lt;&lt; (i+1) &lt;&lt; '\n';
      shared_memory_object::remove("MySharedMemory");
      std::exit(-1);
    }
  
    std::cout &lt;&lt; i &lt;&lt; " values inserted into shared memory" &lt;&lt; '\n';
    return 0;
  }
  </code></pre>
  
  <p>unorder_map_slave.cc</p>
  
  <pre><code>#include &lt;cstdlib&gt;
  #include &lt;iostream&gt;
  #include &lt;boost/interprocess/managed_shared_memory.hpp&gt;
  #include &lt;boost/interprocess/allocators/allocator.hpp&gt;
  #include &lt;boost/unordered_map.hpp&gt;   //boost::unordered_map
  #include &lt;functional&gt;      //std::equal_to
  #include &lt;boost/functional/hash.hpp&gt; //boost::hash
  
  #include "map-value.h"
  
  using namespace boost::interprocess;
  using namespace ip;
  
  int
  main (int argc, char *argv[])
  {
    using namespace boost::interprocess;
  
    int c;
    bool clear_shmem = false;
  
    while ((c = getopt(argc, argv, "c")) != -1) {
      switch(c) {
        case 'c':
          clear_shmem = true;
          break;
        default:
          std::cout &lt;&lt; "Invalid input params to " &lt;&lt; argv[0] &lt;&lt; '\n';
          break;
      }
    }
  
    try
    {
      managed_shared_memory segment(open_or_create, "MySharedMemory", 65536);
  
      // Again the map&lt;Key, MappedType&gt;'s value_type is std::pair&lt;const Key, MappedType&gt;,
          // so the allocator must allocate that pair.
      typedef int  KeyType;
      //typedef size_t  MappedType;
      typedef std::pair&lt;const int, MapValue&lt;shmem::string&gt;::MapValuePtr&gt; ValueType;
  
      // Assign allocator
      typedef allocator&lt;ValueType, managed_shared_memory::segment_manager&gt; ShmemAllocator;
  
      // The map
      typedef boost::unordered_map&lt;KeyType, MapValue&lt;shmem::string&gt;::MapValuePtr
                                   , boost::hash&lt;KeyType&gt;, std::equal_to&lt;KeyType&gt;
                                   , ShmemAllocator&gt; SharedHashMap;
  
      // Initialize the shared memory STL-compatible allocator
      ShmemAllocator alloc_inst(segment.get_segment_manager());
  
      // access the map in SHM through the offset ptr
      SharedHashMap::iterator iter;
      offset_ptr&lt;SharedHashMap&gt; m_pmap = segment.find&lt;SharedHashMap&gt;("SharedHashMap").first;
  
      if (!m_pmap) {
        std::cout &lt;&lt; "Shared memory not initalized... Exiting..." &lt;&lt; '\n';
        std::exit(-1);
      }
  
      iter = m_pmap-&gt;begin();
      std::cout&lt;&lt; "size: " &lt;&lt; m_pmap-&gt;size();
  
      using MVString = MapValue&lt;shmem::string&gt;;
      using MVStringPtr = MVString::MapValuePtr;
      using MVStringDeleter = MVString::MVDeleter;
  
      for (; iter != m_pmap-&gt;end(); iter++) {
        MapValue&lt;shmem::string&gt;::MapValuePtr val(iter-&gt;second);
        std::cout &lt;&lt; "\n " &lt;&lt; iter-&gt;first &lt;&lt; " : "
                  &lt;&lt; "value: " &lt;&lt; val-&gt;GetValue() &lt;&lt; ". "
                  &lt;&lt; "timestamp: " &lt;&lt; val-&gt;GetTimestamp() &lt;&lt; '\n';
      }
  
      std::cout&lt;&lt; "\n";
    }
  
    catch (const bip::interprocess_exception&amp; e) {
      std::cout &lt;&lt; "error: " &lt;&lt; e.what() &lt;&lt; ". "
                &lt;&lt; "error-code: " &lt;&lt; strerror(e.get_error_code()) &lt;&lt; ". "
                &lt;&lt; "error-msg: " &lt;&lt; e.get_native_error() &lt;&lt; ". " &lt;&lt; '\n';
      shared_memory_object::remove("MySharedMemory");
    }
  
    if (clear_shmem) {
      shared_memory_object::remove("MySharedMemory");
    }
  
    return 0;
  }
  </code></pre>