以下是一个小型的读者作家计划。作者将值写入地图地图,写入成功。 还有一个名为reader的进程读取SHM的内容,读者在读取外部映射的键时没有问题,但是如果我们尝试访问内部映射的内容则会崩溃。 我检查了容器大小,它为case1打印2,这很好,因为内部地图包含2个关键字“case1”的元素。
然而,当我尝试访问内部地图程序崩溃时,我访问内部地图的方式不正确。以下是我正在使用的代码片段。
#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
#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
答案 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
注意:
这是非常笨拙的代码。
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的适当类中将其抽象出来
据我所知,
// 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]
我从未听说过这个。你能指出陈述这一点的文件吗?