boost::interprocess::managed_shared_memory crashes program
boost, boost-interprocess, c++, shared-memory
Solution
It looks like you're putting the `std::string` type in shared memory, which won't work because it will allocate non-shared memory for itself. You should use the `boost::interprocess::basic_string` type instead from `<boost/interprocess/containers/string.hpp>`. There is an example of putting a string in a map here.
To answer what you asked in a comment above, the value returned by `string::c_str()` becomes invalid after the string is destructed. This means that accessing the pointer returned by `memory()` will cause undefined behavior.
Problem
My goal is to create a template singleton class called SharedMemory that can store a given data structure in a map in shared memory using boost::interprocess::managed_shared_memory. ``` #ifndef SHARED_MEMORY_H_ #define SHARED_MEMORY_H_ #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <functional> #include <string> #include <utility> #include <map> using namespace boost::interprocess; template<typename T> class SharedMemory { typedef std::pair<std::string, T> ValueType; typedef allocator<ValueType, managed_shared_memory::segment_manager> ShmemAllocator; typedef map<std::string, T, std::less<std::string>, ShmemAllocator> SharedMap; public: static SharedMemory<T>& instance(); void Create(); void Destory(); void insert(T* t); std::map<std::string, T> getMapOfRecords(); private: SharedMemory(); ~SharedMemory(){delete m_segment;} void Initialize(); managed_shared_memory* m_segment; std::size_t m_size; }; template<typename T> inline void SharedMemory<T>::Create() { Destory(); m_segment = new managed_shared_memory(create_only, T::memory(), m_size); ShmemAllocator alloc_inst (m_segment->get_segment_manager()); m_segment->construct<SharedMap>("SageMap")(std::less<std::string>(), alloc_inst); } template<typename T> inline void SharedMemory<T>::Destory() { shared_memory_object::remove(T::memory()); } template<typename T> inline SharedMemory<T>& SharedMemory<T>::instance() { static SharedMemory<T> instance; return instance; } template<typename T> inline SharedMemory<T>::SharedMemory() : m_size(65536) { } template<typename T> inline void SharedMemory<T>::insert(T* t) { SharedMap* mymap = m_segment->find<SharedMap>("SageMap").first; mymap->insert(std::pair<std::string, T>(t->key(), *t)); } template<typename T> inline std::map<std::string, T> SharedMemory<T>::getMapOfRecords() { SharedMap* mymap = m_segment->find<SharedMap>("SageMap").first; return std::map<std::string, T>(mymap->begin(), mymap->end()); } #endif ``` Here is an example of how its used. ``` #include <boost/lexical_cast.hpp> #include <cstring> #include <cstdlib> #include <string> #include <iostream> #include <functional> #include <utility> #include "SharedMemory.hpp" struct simple_type { int i; std::string key() {return boost::lexical_cast<std::string>(i);} static const char* memory() {return std::string("simple_memory_page").c_str();} simple_type(int i): i(i){} }; int main(int argc, char *argv[]) { if(argc == 1) { SharedMemory<simple_type>& test = SharedMemory<simple_type>::instance(); test.Create(); test.insert(new simple_type(1)); test.insert(new simple_type(2)); std::string s(argv[0]); s += " child "; if(0 != std::system(s.c_str())) return 1; test.Destory(); } else { SharedMemory<simple_type>& test = SharedMemory<simple_type>::instance(); std::map<std::string, simple_type> records = test.getMapOfRecords(); for(auto it = records.begin(); it != records.end(); ++it) { std::cout << it->second.i << std::endl; } } return 0; } ``` Here is a stack trace: ``` position_monitor_eu.exe!boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > >::get_pointer() Line 81 + 0x1a bytes C++ position_monitor_eu.exe!boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > >::get() Line 153 + 0x16 bytes C++ position_monitor_eu.exe!boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > >::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > >(const boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > > & ptr={...}) Line 117 + 0x16 bytes C++ position_monitor_eu.exe!boost::intrusive::compact_rbtree_node_traits_impl<boost::interprocess::offset_ptr<void> >::get_left(boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > const > n={...}) Line 124 + 0x17 bytes C++ position_monitor_eu.exe!boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::container::containers_detail::rbtree_node<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,simple_type>,boost::interprocess::offset_ptr<void> >,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void>,1>,0,boost::intrusive::default_tag,3>,boost::container::containers_detail::node_compare<boost::container::containers_detail::value_compare_impl<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,simple_type>,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,boost::container::containers_detail::select1st<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,simple_type> > >,boost::container::containers_detail::rbtree_node<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,simple_type>,boost::interprocess::offset_ptr<void> > >,unsigned int,1> >::begin() Line 273 + 0x42 bytes C++ position_monitor_eu.exe!boost::container::containers_detail::rbtree<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,simple_type>,boost::container::containers_detail::select1st<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,simple_type> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,boost::interprocess::allocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,simple_type>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void>,0>,boost::interprocess::iset_index> > >::begin() Line 493 + 0x28 bytes C++ position_monitor_eu.exe!boost::container::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,simple_type,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,boost::interprocess::allocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,simple_type>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void>,0>,boost::interprocess::iset_index> > >::begin() Line 245 + 0x1a bytes C++ position_monitor_eu.exe!SharedMemory<simple_type>::getMapOfRecords() Line 68 + 0x1e bytes C++ position_monitor_eu.exe!main(int argc=2, char * * argv=0x02b03db8) Line 200 + 0xc bytes C++ position_monitor_eu.exe!__tmainCRTStartup() Line 555 + 0x19 bytes C position_monitor_eu.exe!mainCRTStartup() Line 371 C kernel32.dll!77003677() [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll] ntdll.dll!775cc002() ntdll.dll!775cbfd5() ``` My current issue is the program crashes to calls to `mymap->begin()` in `getMapOfRecords()`.