Ticket #6764: segment_manager_test.cpp

File segment_manager_test.cpp, 3.2 KB (added by Andrey Semashev, 11 years ago)

The test case that demonstrates the problem.

Line 
1#include <cstddef>
2#include <new>
3#include <iostream>
4#include <boost/interprocess/mapped_region.hpp>
5#include <boost/interprocess/shared_memory_object.hpp>
6#include <boost/interprocess/segment_manager.hpp>
7#include <boost/interprocess/sync/mutex_family.hpp>
8#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
9#include <boost/interprocess/offset_ptr.hpp>
10
11// If set to sizeof(void*) then it works
12const unsigned int g_alignment = 32;
13
14// This is the queue descriptor. It's placed at the beginning of the shared memory segment.
15struct queue_descriptor
16{
17 typedef boost::interprocess::segment_manager_base<
18 boost::interprocess::rbtree_best_fit<
19 boost::interprocess::null_mutex_family,
20 boost::interprocess::offset_ptr< void >,
21 g_alignment
22 >
23 > segment_manager;
24
25 // The test works if this data is removed
26 unsigned int data[6];
27
28 // The segment manager manages dynamic memory right after queue_element_descriptors
29 segment_manager m_segment_manager;
30
31 queue_descriptor(std::size_t shm_dynamic_offset, std::size_t shm_dynamic_size) :
32 m_segment_manager(shm_dynamic_size + shm_dynamic_offset, shm_dynamic_offset)
33 {
34 }
35};
36
37// These structures describe queue elements. They are placed after the queue_descriptor in the shared memory.
38struct queue_element_descriptor
39{
40 unsigned int data[8];
41};
42
43int main(int, char*[])
44{
45 // Input parameters: queue geometry
46 const unsigned int capacity = 64, data_size = 460800;
47
48 // This is where queue_element_descriptors start, aligned to g_alignment
49 const unsigned int queue_element_descriptor_offset = (sizeof(queue_descriptor) + (g_alignment - 1)) & (~(g_alignment - 1));
50
51 // 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?).
52 const std::size_t elem_alloc_size = ((data_size + (g_alignment - 1U)) & (~(g_alignment - 1U))) + 64;
53
54 const std::size_t shm_static_size = sizeof(queue_descriptor) + capacity * sizeof(queue_element_descriptor);
55 const std::size_t shm_dynamic_size = elem_alloc_size * capacity;
56 const std::size_t shm_dynamic_offset = queue_element_descriptor_offset + capacity * sizeof(queue_element_descriptor);
57 const std::size_t shm_size = shm_static_size + shm_dynamic_size;
58
59 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;
60
61 // Create shared memory
62 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);
63 storage_shared_mem.truncate(shm_size);
64
65 // Map memory into our address space
66 boost::interprocess::mapped_region storage_region = boost::interprocess::mapped_region(storage_shared_mem, boost::interprocess::read_write);
67
68 // This is where it fails
69 new (storage_region.get_address()) queue_descriptor(shm_dynamic_offset, shm_dynamic_size);
70
71 static_cast< queue_descriptor* >(storage_region.get_address())->~queue_descriptor();
72 boost::interprocess::shared_memory_object::remove("/segment_manager_test");
73
74 std::cout << "success" << std::endl;
75
76 return 0;
77}