#include #include #include #include #include #include #include #include #include // If set to sizeof(void*) then it works const unsigned int g_alignment = 32; // This is the queue descriptor. It's placed at the beginning of the shared memory segment. struct queue_descriptor { typedef boost::interprocess::segment_manager_base< boost::interprocess::rbtree_best_fit< boost::interprocess::null_mutex_family, boost::interprocess::offset_ptr< void >, g_alignment > > segment_manager; // The test works if this data is removed unsigned int data[6]; // The segment manager manages dynamic memory right after queue_element_descriptors segment_manager m_segment_manager; queue_descriptor(std::size_t shm_dynamic_offset, std::size_t shm_dynamic_size) : m_segment_manager(shm_dynamic_size + shm_dynamic_offset, shm_dynamic_offset) { } }; // These structures describe queue elements. They are placed after the queue_descriptor in the shared memory. struct queue_element_descriptor { unsigned int data[8]; }; int main(int, char*[]) { // Input parameters: queue geometry const unsigned int capacity = 64, data_size = 460800; // This is where queue_element_descriptors start, aligned to g_alignment const unsigned int queue_element_descriptor_offset = (sizeof(queue_descriptor) + (g_alignment - 1)) & (~(g_alignment - 1)); // Align data size to g_alignment. Add 64 bytes as an overhead the segment manager might need for each allocation (BTW: is there a better estimate?). const std::size_t elem_alloc_size = ((data_size + (g_alignment - 1U)) & (~(g_alignment - 1U))) + 64; const std::size_t shm_static_size = sizeof(queue_descriptor) + capacity * sizeof(queue_element_descriptor); const std::size_t shm_dynamic_size = elem_alloc_size * capacity; const std::size_t shm_dynamic_offset = queue_element_descriptor_offset + capacity * sizeof(queue_element_descriptor); const std::size_t shm_size = shm_static_size + shm_dynamic_size; std::cout << "elem_alloc_size = " << elem_alloc_size << ", shm_static_size = " << shm_static_size << ", shm_dynamic_size = " << shm_dynamic_size << ", shm_dynamic_offset = " << shm_dynamic_offset << std::endl; // Create shared memory boost::interprocess::shared_memory_object storage_shared_mem = boost::interprocess::shared_memory_object(boost::interprocess::open_or_create, "/segment_manager_test", boost::interprocess::read_write); storage_shared_mem.truncate(shm_size); // Map memory into our address space boost::interprocess::mapped_region storage_region = boost::interprocess::mapped_region(storage_shared_mem, boost::interprocess::read_write); // This is where it fails new (storage_region.get_address()) queue_descriptor(shm_dynamic_offset, shm_dynamic_size); static_cast< queue_descriptor* >(storage_region.get_address())->~queue_descriptor(); boost::interprocess::shared_memory_object::remove("/segment_manager_test"); std::cout << "success" << std::endl; return 0; }