【发布时间】:2014-10-21 20:11:30
【问题描述】:
以下是一个小型读写器程序。写入器将值写入映射映射,写入成功。 还有一个叫做 reader 的进程读取 SHM 的内容,reader 读取外部 map 的 key 没有问题,但是如果我们尝试访问内部 map 的内容,它会崩溃。 我检查了容器大小,它为 case1 打印了 2,这很好,因为内部映射包含键“case1”的 2 个元素。
但是,当我尝试访问内部地图时,程序崩溃,是我访问内部地图的方式不正确。以下是我正在使用的代码 sn-ps。
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;
}
堆栈跟踪:
运行程序时的输出 =>
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
【问题讨论】:
-
您的代码太复杂,无法发现可能有问题的地方,您能简化为 MWE 吗? (见stackoverflow.com/help/mcve)
-
看起来你想读取一个不存在的节点
-
@Maciej 为什么内图的尺寸会是 2 呢?
-
这个例子很大,但我看到你保存了迭代器。你确定执行距离函数时它们指向的元素仍然存在吗?
-
用代码行 MappedType::iterator iti = (iter->second).begin(), MappedType::iterator iti_end = (iter->second).end();我没有看到迭代器失效的可能性,映射的映射在共享内存中,这可能是导致问题的原因吗?