Boost Interprocess:托管共享内存错误

时间:2018-05-07 13:49:56

标签: c++ memory boost

我正在使用boosts进程间库来共享多个程序之间的内存。 3或4个其他程序将在cust_order中读取和写入共享内存内容。需要序列化对存储空间的访问。

在下面的示例程序中,引擎循环使用risk_queue的内容,如果已填充,则获取第一个cust_order编号并找到该订单以进行处理。

    每个程序使用的objects.h头文件中的
  • struct cust_order {
      int ID;
      char CLID[128];
      int CUST_ID;
      char ORDER_STATUS;
    };
    
    cust_order o;
    
    boost::interprocess::managed_shared_memory
        cust_order_segment(boost::interprocess::open_or_create, "cust_order",
                           65536 * 100);
    
    typedef int cust_order_KeyType;
    typedef cust_order cust_order_MappedType;
    typedef std::pair<const int, cust_order> cust_order_ValueType;
    
    typedef boost::interprocess::allocator<
        cust_order_ValueType,
        boost::interprocess::managed_shared_memory::segment_manager>
        cust_order_ShmemAllocator;
    
    typedef boost::interprocess::map<cust_order_KeyType, cust_order_MappedType,
                                     std::less<cust_order_KeyType>,
                                     cust_order_ShmemAllocator>
        cust_order_MySHMMap;
    cust_order_MySHMMap::iterator cust_order_iter;
    
    boost::interprocess::managed_shared_memory
        risk_queue_segment(boost::interprocess::open_or_create, "risk_queue",
                           65536 * 100);
    typedef int risk_queue_KeyType;
    typedef int risk_queue_MappedType;
    typedef std::pair<const int, int> risk_queue_ValueType;
    typedef boost::interprocess::allocator<
        risk_queue_ValueType,
        boost::interprocess::managed_shared_memory::segment_manager>
        risk_queue_ShmemAllocator;
    
    typedef boost::interprocess::map<risk_queue_KeyType, risk_queue_MappedType,
                                     std::less<risk_queue_KeyType>,
                                     risk_queue_ShmemAllocator>
        risk_queue_MySHMMap;
    risk_queue_MySHMMap::iterator risk_queue_iter;
    
  • engine.cpp中的
  •  int main() {
    
         risk_queue_ShmemAllocator risk_queue_alloc_inst(
                 risk_queue_segment.get_segment_manager());
    
         cust_order_ShmemAllocator cust_order_alloc_inst(
                 cust_order_segment.get_segment_manager());
    
         for (; 0 < 1;) {
    
             boost::interprocess::offset_ptr<risk_queue_MySHMMap> risk_queue_m_pmap =
                 risk_queue_segment.find<risk_queue_MySHMMap>("risk_queue").first;
    
             boost::interprocess::offset_ptr<cust_order_MySHMMap> cust_order_m_pmap =
                 cust_order_segment.find<cust_order_MySHMMap>("cust_order").first;
    
             risk_queue_iter = risk_queue_m_pmap->begin();
             if (risk_queue_iter != risk_queue_m_pmap->end()) {
                 ordid = risk_queue_iter->second;
                 cust_order_m_pmap->find(ordid)->second = o;
                 o.ORDER_STATUS = '0';
                 o = cust_order_m_pmap->find(ordid)->second;
                 risk_queue_m_pmap->erase(ordid);
             }
         };
         return 0;
     }
    

这是程序完美运行几秒钟后出现的错误:

engine: /usr/include/boost/intrusive/bstree.hpp:1331: boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::iterator boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::insert_unique_commit(boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::reference, const insert_commit_data&) [with ValueTraits = boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::pair<const int, event>, boost::interprocess::offset_ptr<void>, (boost::container::tree_type_enum)0, true>, boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::dft_tag, 3>; VoidOrKeyOfValue = void; VoidOrKeyComp = boost::container::value_to_node_compare<boost::container::container_detail::tree_node<std::pair<const int, event>, boost::interprocess::offset_ptr<void>, (boost::container::tree_type_enum)0, true>, boost::intrusive::tree_value_compare<boost::interprocess::offset_ptr<std::pair<const int, event>, long int, long unsigned int, 0>, std::less<int>, boost::container::container_detail::select1st<int>, false> >; SizeType = long unsigned int; bool ConstantTimeSize = true; boost::intrusive::algo_types AlgoType = (boost::intrusive::algo_types)5; HeaderHolder = void; boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::iterator = boost::intrusive::tree_iterator<boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::pair<const int, event>, boost::interprocess::offset_ptr<void>, (boost::container::tree_type_enum)0, true>, boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::dft_tag, 3>, false>; boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::reference = boost::container::container_detail::tree_node<std::pair<const int, event>, boost::interprocess::offset_ptr<void>, (boost::container::tree_type_enum)0, true>&; boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::insert_commit_data = boost::intrusive::insert_commit_data_t<boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> >, long int, long unsigned int, 0> >]: Assertion `( p == this->end() || !this->comp()(*p, value) )' failed.
Aborted (core dumped)

请你帮我理解错误。让我知道,如果有更好的方式让我做我需要做的事情。

1 个答案:

答案 0 :(得分:2)

好的,所以我查看了你的代码。你自己说:

  

需要序列化对内存空间的访问。

那么,为什么不帮你?

备注

简化标题:

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/map.hpp>

struct cust_order {
    int  ID;
    char CLID[128];
    int  CUST_ID;
    char ORDER_STATUS;
};

namespace bip = boost::interprocess;

namespace Shared {
    using Segment = bip::managed_shared_memory;
    using Manager = Segment::segment_manager;
    template <typename T> using Alloc = bip::allocator<T, Manager>;

    template <typename K, typename V, typename Cmp = std::less<K> >
        using Map = bip::map<K, V, Cmp, Alloc<typename bip::map<K, V>::value_type> >;
}

using OrderTable = Shared::Map<int, cust_order>;
using RiskQueue = Shared::Map<int, int>;

简化主要内容:

int main() {
    Shared::Segment cust_order_segment(bip::open_or_create, "cust_order", 65536 * 100);
    Shared::Segment risk_queue_segment(bip::open_or_create, "risk_queue", 65536 * 100);

    auto risk_queue  = risk_queue_segment.find_or_construct<RiskQueue>("risk_queue")(risk_queue_segment.get_segment_manager());
    auto order_table = cust_order_segment.find_or_construct<OrderTable>("cust_order")(cust_order_segment.get_segment_manager());

    while (true) {
        while (!risk_queue->empty()) {

            auto it    = risk_queue->begin();
            auto ordid = it->second;

            order_table->at(ordid).ORDER_STATUS = '0';
            risk_queue->erase(ordid);
        }
    }
}

最值得注意的事情:

  1. 没有任何同步(除了段管理器内的一些细节)
  2. 您没有检查任何错误(丢失的细分,丢失的对象,缺少从risk_queue引用的订单)
  3. 为什么数据结构在不同的段中?
  4. 为什么你在一个紧凑的循环中运行,好像你正在处理无锁数据结构?
  5. 为什么你滥用地图就好像他们是优先级队列一样?界面与预期用途
  6. 不匹配
  7. 最有趣的是,由于RiskQueue按键排序,并被视为队列,因此我们必须假设Key类型表示风险/优先级。

    映射类型显然是订单ID,它指的是客户订单表。到目前为止一切都很好。

    但是,你做了

        risk_queue->erase(ordid);
    

    这完全是令人费解的,因为它将订单ID视为&#34;风险队列的关键&#34;?队列没有密钥,我们只是得出结论&#34; key&#34;风险表示优先级(因此它不是订单ID)。

    即使猜测它应该是order_table->erase(ordid),也没有多大意义,因为那时在删除之前设置订单状态的目的是什么。

    我只能断定该行是一个错误,需要

        risk_queue->erase(it);
    
  8. 当然,在同步处理之前,这一切都不重要。

    如果您有许多订单处理客户,我建议您可以使用信号量。一切都会变得更安全,也更少浪费CPU能力。

    如果您确实必须拥有无锁数据访问权限,请确保数据结构 实际上是无锁的,并确保您保持一致性(&#39; sa hard 问题因为您决定将数据拆分为两个结构。)