I wanted to implement, some queue of messages (based on vector) to handling in some way data from the network and to do this I used shared memory to save messages and I encountered an issue related to it, the thing is that my code works well when I run it first time, when I want to run it once again I get segfaut when I want to assign a new value to string in my queue in shared memory, actually in my case when I want to move it (the same problem exists when I want to copy it). The problem doesn't exist when SSO is working, so when I have small string enough. What did I wrong ?
#include <atomic>
#include <exception>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
namespace bip = boost::interprocess;
struct BadSharedMemoryAccess final : public std::exception
{
BadSharedMemoryAccess(std::string&& msg):
msg_{std::move(msg)}
{}
virtual const char* what() const noexcept
{
return msg_.c_str();
}
private:
std::string msg_;
};
struct Message
{
bip::string message_;
};
template<typename Alloc>
class MyCustomData final
{
public:
using allocator_type = typename Alloc::template rebind<Message>::other;
MyCustomData(std::size_t number_of_messages, Alloc alloc = {}) :
init_add_index_{0},
init_handle_index_{-1},
messages_{number_of_messages, alloc}
{}
public:
uint_fast64_t init_add_index_;
int_fast64_t init_handle_index_;
std::vector<Message, Alloc> messages_;
// bip::vector<data::Message, Alloc> messages_;
};
template<typename DataType, typename DataAllocator>
class SharedMemory
{
public:
template<typename... Args>
SharedMemory(std::string const& shm_segment_name, std::size_t const segment_size,
std::string const& shm_object_name, Args&&... args) :
shm_object_name_{shm_object_name}
{
std::cout << "attempt to allocate space for shared memory segment " << shm_segment_name
<< ", size: ." << segment_size << std::endl;
setSharedMemorySize(shm_segment_name, segment_size);
DataAllocator const allocInstance{shm_.get_segment_manager()};
data_ = shm_.find_or_construct<DataType>(shm_object_name.c_str())(std::forward<Args>(args)..., allocInstance);
if (data_)
std::cout << "shared memory segment has been allocated" << std::endl;
else
std::cout << "shared memory has not been constructed or founded" << std::endl;
}
virtual ~SharedMemory()
{
std::cout << "shared memory segment will be closed." << std::endl;
}
void setSharedMemorySize(std::string const& shm_segment_name, std::size_t const segment_size)
{
auto page_size = bip::mapped_region::get_page_size();
auto const page_increase_rate{2};
while (page_size < segment_size)
{
page_size *= page_increase_rate;
}
std::cout <<"seting page size: " << page_size << std::endl;
shm_ = bip::managed_shared_memory{bip::open_or_create, shm_segment_name.c_str(), page_size};
std::cout << "space for shared memory has been successfully allocated." << std::endl;
}
DataType& getData()
{
if (not data_)
throw BadSharedMemoryAccess{"cannot access " + shm_object_name_};
return *data_;
}
protected:
DataType* data_;
private:
std::string const shm_object_name_;
bip::managed_shared_memory shm_;
};
namespace sharable
{
using DataAllocator = bip::allocator<Message, bip::managed_shared_memory::segment_manager>;
template<typename Alloc>
using DataType = MyCustomData<Alloc>;
}
int main()
{
std::size_t const max_number_of_elements_in_container{1000000};
auto shmem_data = std::make_shared<SharedMemory<MyCustomData<sharable::DataAllocator>, sharable::DataAllocator>>(
"SHM_SEGMENT", sizeof(MyCustomData<sharable::DataAllocator>) +
(max_number_of_elements_in_container * sizeof(Message) * 2),
"SHM_CONTAINER", max_number_of_elements_in_container);
std::vector<bip::string> feed{max_number_of_elements_in_container};
for (std::size_t i = 0; i < max_number_of_elements_in_container; ++i)
{
std::string s{"blablabla11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + std::to_string(i)};
feed[i] = s.c_str();
}
auto& data = shmem_data->getData();
auto& shmem_vec = data.messages_;
std::cout << "addr: " << shmem_vec.data() << std::endl;
for (std::size_t i = 0; i < max_number_of_elements_in_container; ++i)
{
// if (i == 0)
// std::cout << "msg: " << shmem_vec[i].message_ << std::endl;
auto msg = feed[i];
shmem_vec[i].message_ = std::move(msg);
}
return 0;
}
Aucun commentaire:
Enregistrer un commentaire