ошибка компиляции push round_buffer push_back

Я реализую boost::circular_buffer в boost::managed_shared_memory. Я использовал пример кода, демонстрирующий вектор в общей памяти здесь. Я сделал следующие изменения:

1) typedef boost::circular_buffer<int, ShmemAllocatorCB> MyCircularBuffer;

2) MyCircularBuffer *circbuff = segment.construct<MyCircularBuffer>("MyCB")(alloc_inst);

3) circbuff->push_back(1);

Код выдает ошибку компиляции в строке №3. Ошибка

error C2665: 'operator new' : none of the 5 overloads could convert all the argument types c:\boost2005\boost\circular_buffer\base.hpp 1470

Из документации я понимаю функцию push_back ожидает одну из этих 3 форм:

void push_back(param_value_type); void push_back(rvalue_type); void push_back();

Я попробовал вызов пустого параметра, попытался привести 1 к param_value_type, rvalue_type, но ни один из них не работает. Это может быть простой ошибкой, но я не мог понять это уже довольно давно. Любая помощь приветствуется. Спасибо.

Изменить:

typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocatorCB;

managed_shared_memory segment(create_only, "MySharedMemory", 65536);

const ShmemAllocatorCB alloc_inst (segment.get_segment_manager());


person Maverick    schedule 30.06.2014    source источник
comment
Что ж, проблема, похоже, заключается в том, чтобы создать объект, а не протолкнуть его. Я подозреваю, что ошибка сохранится, если вы прокомментируете вызов push_back. Я думаю, вам нужно уточнить больше. В частности: как определяется ShmemAllocatorCB и что такое alloc_inst?   -  person hfhc2    schedule 30.06.2014
comment
@hfhc2: Пожалуйста, проверьте правку. Ошибка возникает именно при вызове push_back(). Если я закомментирую это, программа скомпилируется просто отлично.   -  person Maverick    schedule 01.07.2014


Ответы (2)


Похоже, что циклический буфер Boost в какой-то момент использует необработанные указатели для отладки. Это, к сожалению, запрещено:

Boost предоставляет некоторые ссылки на эту тему:

Таким образом, скомпилируйте свой код без поддержки отладки round_buffer, определив BOOST_CB_DISABLE_DEBUG или NDEBUG определения препроцессора.

РЕДАКТИРОВАТЬ: Вот рабочий пример:

(проверено с BOOST_LIB_VERSION = 1_49)

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/circular_buffer.hpp>
#include <iostream>
#include <string>
#include <cstdlib> //std::system

using namespace boost::interprocess;

//Define an STL compatible allocator of ints that allocates from the managed_shared_memory.
//This allocator will allow placing containers in the segment
typedef allocator<int, managed_shared_memory::segment_manager>  ShmemAllocatorCB;

//Alias a vector that uses the previous STL-like allocator so that allocates
//its values from the segment
typedef boost::circular_buffer<int, ShmemAllocatorCB> MyCircularBuffer;

//Main function. For parent process argc == 1, for child process argc == 2
int main(int argc, char *argv[])
{
   if(argc == 1){ //Parent process
      //Remove shared memory on construction and destruction
      struct shm_remove
      {
         shm_remove() { shared_memory_object::remove("MySharedMemory"); }
         ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
      } remover;

      //Create a new segment with given name and size
      managed_shared_memory segment(create_only, "MySharedMemory", 65536);

      //Initialize shared memory STL-compatible allocator
      const ShmemAllocatorCB alloc_inst (segment.get_segment_manager());

      //Construct a buffer named "MyCB" in shared memory with argument 10 (for size) and alloc_inst
      MyCircularBuffer *circbuff = segment.construct<MyCircularBuffer>("MyCB")(10, alloc_inst);

      for(int i = 0; i < 100; ++i)  //Insert data in the buffer, with overflows
         circbuff->push_back(i);

      //Launch child process
      std::string s(argv[0]); s += " child ";
      if(0 != std::system(s.c_str()))
         return 1;

      //Check child has destroyed the buffer
      if(segment.find<MyCircularBuffer>("MyCB").first)
         return 1;
   }
   else{ //Child process
      //Open the managed segment
      managed_shared_memory segment(open_only, "MySharedMemory");

      //Find the buffer using the c-string name
      MyCircularBuffer *circbuff = segment.find<MyCircularBuffer>("MyCB").first;

      //Use buffer in reverse order
      std::cout << "Child got: " << (*circbuff)[3] << "\n"; // 93

      //When done, destroy the buffer from the segment
      segment.destroy<MyCircularBuffer>("MyCB");
   }

   return 0;
};

Чтобы выполнить его:

g++ -DBOOST_CB_DISABLE_DEBUG -DNDEBUG cb_ipc.cpp -o cb_ipc -lboost_system -lrt

Чтобы запустить его:

./cb_ipc
Child got: 93
person ftwl    schedule 30.06.2014
comment
Все эти сумасшедшие способы делать IPC! Абсолютно сумасшедший! - person ftwl; 30.06.2014
comment
@ftwl: спасибо за предложение, но я уже пробовал, и это не работает. Хотя странно, что если я изменю настройки сборки на Release вместо Debug, ошибка изменится на none of the 4 overloads could convert all the argument types . - person Maverick; 01.07.2014
comment
@sehe: Спасибо за предложение очереди spsc, я попробую. Хотя, не могли бы вы прокомментировать, что не так с оригинальным вопросом. Я пытался использовать препроцессоры, но это не сработало. - person Maverick; 01.07.2014
comment
@Maverick ответ уже дал объяснение, иначе я бы опубликовал точно такой же ответ. И да, это заставило код скомпилироваться. - person sehe; 02.07.2014
comment
@ftwl: извините, я не упомянул раньше, я использую MSVC 2010 и повышаю 1_55. чтобы скомпилировать это. Я попробовал код, который вы разместили, но ошибка все еще сохраняется. Я добавил препроцессоры в настройках проекта. Есть ли что-то еще, о чем мне нужно позаботиться в Visual Studio? - person Maverick; 02.07.2014
comment
@Maverick: я не уверен ... Может быть, попробуйте добавить определения в самый верх файла: #define BOOST_CB_DISABLE_DEBUG #define NDEBUG - person ftwl; 02.07.2014
comment
@ftwl: это тоже не работает. Эта штука сводит меня с ума! В любом случае, дайте мне знать, если вы выясните это в любой момент. Спасибо за вашу помощь! - person Maverick; 02.07.2014

Проблема здесь в том, что вы неправильно устанавливаете емкость circ_buffer. Я бы предположил, что емкость равна нулю, и, следовательно, вы не можете нажать.

После создания циркулярного_буфера установите требуемый объем емкости.

#define BOOST_CB_DISABLE_DEBUG

#include <boost/circular_buffer.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>

using namespace boost;
using namespace boost::interprocess;

typedef allocator<T, managed_shared_memory::segment_manager> cb_alloc;
typedef circular_buffer<T, cb_alloc> cb;

managed_shared_memory* m_mem_segment;                                               
cb* m_buffer;

//  Create shared memory segment of a size able to hold the max updates.
m_mem_segment = new managed_shared_memory(open_or_create, NAMED_MEMORY, MEMORY_SIZE);       

if (m_mem_segment == nullptr) {
    return false;
}
//  Get the segement manager for allocating a circular buffer.
const cb_alloc alloc_inst(m_mem_segment->get_segment_manager());                            

//  Create a circular buffer in the shared memory segment.
m_buffer = m_mem_segment->find_or_construct<cb>(NAMED_BUFFER)(alloc_inst);                  

if (m_mem_segment == nullptr) {
    return false;
}

//  Set the capacity if not set (zero) (this must be set!)
if (m_buffer->capacity() <= 0) {                                                    
    m_buffer->set_capacity(50);
}

Вы можете нажимать на это нормально, я тестировал с несколькими процессами, обменивающимися данными. Это простой пример, вы, очевидно, должны реализовать собственную синхронизацию между процессами, используя named_mutex или семафоры и т.д.

person Bumble    schedule 11.08.2014