【问题标题】:Boost interprocess vector crashing提升进程间向量崩溃
【发布时间】:2020-08-06 03:22:40
【问题描述】:

下面的程序在共享内存中重复创建 0.1 MB 的向量。每次没有足够的空间来创建向量或调整向量大小时,共享内存段就会增长 1 MB。最终,程序在vec->resize 调用(在代码中标记)时崩溃,并出现 SIGBUS 错误。堆栈跟踪如下。崩溃通常发生在共享内存段大约 8G 时。我有 16G 的 RAM,其中只有大约 1G 被除此之外的其他进程使用。

我是在增加内存还是在此处错误地使用了 boost::interproces::vector,或者 boost 库本身是否存在问题?

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <iostream>
#include <unistd.h>

namespace bip = boost::interprocess;  
template <typename T>
using Alloc   = bip::allocator<T, bip::managed_shared_memory::segment_manager>;
typedef bip::vector<uint8_t, boost::container::scoped_allocator_adaptor<Alloc<uint8_t> > > DataVector;


int main(int argc, char** argv){
  std::string shm_name = "test";
  int size_increment = 1000000; // 1 MB
  int vec_size = 100000; // 0.1 MB
  assert(vec_size < size_increment);

  bip::shared_memory_object::remove(shm_name.c_str());

  bip::managed_shared_memory* segment = new bip::managed_shared_memory(bip::open_or_create, shm_name.c_str(), size_increment);

  for(int i = 0; true; i++){
    std::cout << i << std::endl;
    std::string var_name = std::to_string(i);
    DataVector* vec = NULL;

    // create the vector
    try{
      vec = segment->find_or_construct<DataVector>(var_name.c_str())(segment->get_segment_manager());
    }
    catch(std::exception& ex){
      // grow
      std::cout << "1 growing: " << ex.what() << std::endl;
      delete segment;
      bip::managed_shared_memory::grow(shm_name.c_str(), size_increment);
      segment = new bip::managed_shared_memory(bip::open_only, shm_name.c_str());
      std::cout << "1 done growing" << std::endl;

      vec = segment->find_or_construct<DataVector>(var_name.c_str())(segment->get_segment_manager());
    }

    // make sure the vector isn't null
    if(vec == NULL){
      std::cout << "1 vec was NULL" << std::endl;
      return 1;
    }

    // grow the vector
    try{
      vec->resize(vec_size); // SIGBUS crash happens here
    }
    catch(std::exception& ex){
      // grow
      std::cout << "2 growing: " << ex.what() << std::endl;
      delete segment;
      bip::managed_shared_memory::grow(shm_name.c_str(), size_increment);
      segment = new bip::managed_shared_memory(bip::open_only, shm_name.c_str());
      std::cout << "2 done growing" << std::endl;

      vec = segment->find<DataVector>(var_name.c_str()).first;
      if(vec == NULL){
    std::cout << "2 vec was NULL" << std::endl;
    return 1;
      }
      vec->resize(vec_size);
    }

    usleep(1000); // sleep 1ms
  }


  return 0;
}
Program terminated with signal SIGBUS, Bus error.
#0  __memset_avx2_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:141
141 ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S: No such file or directory.

#0  __memset_avx2_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:141
#1  0x0000562cec17143c in boost::container::uninitialized_value_init_alloc_n<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>, unsigned char*>(boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>&, boost::container::allocator_traits<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >> >::size_type, unsigned char*) (n=100000, r=0x7fd0d0c1ce90 <error: Cannot access memory at address 0x7fd0d0c1ce90>)
    at /usr/include/boost/container/detail/copy_move_algo.hpp:588
#2  0x0000562cec16e9b5 in boost::container::container_detail::insert_value_initialized_n_proxy<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>, unsigned char*>::uninitialized_copy_n_and_update(boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>&, unsigned char*, unsigned long) const (this=0x7ffc3a961780, a=..., p=0x7fd0d0c1ce90 <error: Cannot access memory at address 0x7fd0d0c1ce90>, 
    n=100000) at /usr/include/boost/container/detail/advanced_insert_int.hpp:126
#3  0x0000562cec16e6a3 in boost::container::vector<unsigned char, boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >> >::priv_forward_range_insert_new_allocation<boost::container::container_detail::insert_value_initialized_n_proxy<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>, unsigned char*> >(unsigned char*, unsigned long, unsigned char*, unsigned long, boost::container::container_detail::insert_value_initialized_n_proxy<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>, unsigned char*>) (this=0x7fd0d0c1ce58, new_start=0x7fd0d0c1ce90 <error: Cannot access memory at address 0x7fd0d0c1ce90>, new_cap=100000, pos=0x0, n=100000, insert_range_proxy=...) at /usr/include/boost/container/vector.hpp:2943
#4  0x0000562cec16c0ad in boost::container::vector<unsigned char, boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >> >::priv_forward_range_insert_no_capacity<boost::container::container_detail::insert_value_initialized_n_proxy<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>, unsigned char*> >(boost::interprocess::offset_ptr<unsigned char, long, unsigned long, 0ul> const&, unsigned long, boost::container::container_detail::insert_value_initialized_n_proxy<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>, unsigned char*>, boost::move_detail::integral_constant<unsigned int, 1u>) (this=0x7fd0d0c1ce58, pos=..., n=100000, insert_range_proxy=...) at /usr/include/boost/container/vector.hpp:2682
#5  0x0000562cec16a6f8 in boost::container::vector<unsigned char, boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >> >::priv_forward_range_insert<boost::container::container_detail::insert_value_initialized_n_proxy<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>, unsigned char*> >(boost::interprocess::offset_ptr<unsigned char, long, unsigned long, 0ul> const&, unsigned long, boost::container::container_detail::insert_value_initialized_n_proxy<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>, unsigned char*>) (this=0x7fd0d0c1ce58, pos=..., n=100000, insert_range_proxy=...) at /usr/include/boost/container/vector.hpp:2744
#6  0x0000562cec168ff4 in boost::container::vector<unsigned char, boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >> >::priv_forward_range_insert_at_end<boost::container::container_detail::insert_value_initialized_n_proxy<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>, unsigned char*>, boost::move_detail::integral_constant<unsigned int, 1u> >(unsigned long, boost::container::container_detail::insert_value_initialized_n_proxy<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >>, unsigned char*>, boost::move_detail::integral_constant<unsigned int, 1u>) (this=0x7fd0d0c1ce58, n=100000, insert_range_proxy=...) at /usr/include/boost/container/vector.hpp:2774
#7  0x0000562cec167e43 in boost::container::vector<unsigned char, boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >> >::priv_resize<boost::container::value_init_t>(unsigned long, boost::container::value_init_t const&) (this=0x7fd0d0c1ce58, new_size=100000, u=...) at /usr/include/boost/container/vector.hpp:2602
#8  0x0000562cec167838 in boost::container::vector<unsigned char, boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<unsigned char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >> >::resize(unsigned long) (this=0x7fd0d0c1ce58, new_size=100000) at /usr/include/boost/container/vector.hpp:1460
#9  0x0000562cec164e4f in main (argc=2, argv=0x7ffc3a9620d8) at /home/username/subt/map_database_ws/src/map_database_demo/src/boost_test.cpp:53

【问题讨论】:

  • 1MB 到 8GB 是 8000 调整大小。你真的需要8GB吗?你的程序什么时候停止分配新的内存块?
  • 共享内存限制是多少? ulimit可以解释一下。
  • @UmNyobe 该程序将继续分配,直到没有剩余可分配。如果没有剩余,boost 应该会生成异常并且不会与 SIGBUS 一起崩溃。这个程序只是一个小的自包含示例,模拟我正在开发的另一个程序所做的事情。我希望不需要 8G 附近的任何地方,但我想确保 boost 进程间库没有错误。
  • @tadman Boost 在 /dev/shm 中分配共享内存。根据df,/dev/shm 中可用的最大值约为 8G,所以看起来我正在达到这个限制。感谢您指出了这一点。如果我正确使用它并且正确实现了 boost 库,我仍然认为 boost 应该抛出异常并且不会与 SIGBUS 崩溃。

标签: c++ boost


【解决方案1】:

因此,您遇到了 shm 文件系统的限制。

您当然可以增加大小,但我建议查看托管内存段的开销。尤其是随着有机增长而发生的碎片化。

参见例如Bad alloc is thrown

也许您不能预先保留所有内容,但您可以在调整分段大小时进行碎片整理。

最简单的做法是创建一个具有正确预分配数据结构的新段,然后将数据复制过来。全部完成后,删除旧的并重命名新的。

显然,您这样做可能会耗尽虚拟内存,因此使用managed_mapped_file 可能是必要的/一个好主意,或者至少在调整大小期间暂时使用。

其他链接:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多