Boost interprocess: cout string variable when iterating through a map that references an object from a structure

I use boost :: interprocess to exchange objects between processes. I have two files: "server.cpp", which generates a struct object and passes the object to a map with index int; and the file "client.cpp", which retrieves the memory data and iterates through the data, outputting it to the console.

The structure is as follows:

    struct mydata o {
    string MY_STRING;
    int MY_INT; 
};

And the object:

mydata o;
o.MY_STRING = "hello";
o.MY_INT = 45;

Both the server and the client compile correctly. But for some reason, the client’s executable causes a segmentation error if I try to access a string, and not by swimming or an integer in the client. For example, the following second.MY_INT will be disabled for the console, but second.MY_STRING will throw this error on startup.

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <functional>
#include <utility>
#include <iostream>
#include <string>
#include "objects.cpp" //definitions for objects
using std::string;
using namespace boost::interprocess;

    int main ()
{

    try
    {
            managed_shared_memory segment(open_or_create, "SharedMemoryName",65536);

            //Again the map<Key, MappedType> value_type is std::pair<const Key, MappedType>, so the allocator must allocate that pair.
            typedef int    KeyType;
            typedef order  MappedType;
            typedef std::pair<const int, order> ValueType;

            //Assign allocator 
            typedef allocator<ValueType, managed_shared_memory::segment_manager> ShmemAllocator;

            //The map
            typedef map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> MySHMMap;

            //Initialize the shared memory STL-compatible allocator
            ShmemAllocator alloc_inst (segment.get_segment_manager());

            //access the map in SHM through the offset ptr                                                         
            MySHMMap :: iterator iter;
            offset_ptr<MySHMMap> m_pmap = segment.find<MySHMMap>("MySHMMapName").first;

            iter=m_pmap->begin();
            for(; iter!=m_pmap->end();iter++)
            {
                   //std::cout<<"\n "<<iter->first<<" "<<iter->second;
                   std::cout<<iter->first<<" "<<iter->second.MYINT<<" "<<iter->second.MYSTRING<<"\n";
            }
    }catch(std::exception &e)            
    {
            std::cout<<" error  " << e.what() <<std::endl;
           shared_memory_object::remove("SharedMemoryName");
    }
    return 0;
}

startup error:

Segmentation fault (core dumped)

, , ( ), .

+4
3

. char , :

std::cout<<iter->first<<" "<<iter->second.ORDERTYPE<<" "<<string(iter->second.MYID)<<"\n";

, :

struct order {
    char MYID[100];
    int ORDERTYPE;
    char DATE_UPDATED[64];
};
order o

:

m_pmap->insert(std::pair<const int, order>(i, (order)o));

, , , .

+1

, std::string , .

Interprocess string . , boost::container::basic_string<> .

.

, (ad nauseam), .

, , , , , .

Live On Coliru

#include <boost/interprocess/managed_shared_memory.hpp>

#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/string.hpp>

#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/container/scoped_allocator.hpp>

#include <iostream>
#include <string>

namespace bip = boost::interprocess;

namespace Shared {
    using Segment = bip::managed_shared_memory;
    using Manager = Segment::segment_manager;

    template <typename T> using Alloc 
        = boost::container::scoped_allocator_adaptor<bip::allocator<T, Manager> >;

    using String = bip::basic_string<char, std::char_traits<char>, Alloc<char> >;

    template <typename K, typename V, typename Cmp = std::less<K> > using Map 
        = bip::map<K, V, Cmp, Alloc<std::pair<K const, V> > >;

    struct Order {
        using allocator_type = Alloc<char>;

        template <typename S, typename Alloc>
        Order(int i, S const& s, Alloc alloc = {}) : i(i), s(s, alloc) {}

        int    i;
        String s;
    };
}

int main() {
    try {
        using namespace Shared;
        Segment segment(bip::open_or_create, "095540a3-ceaa-4431-828d-df21d5e384ae", 65536);

        auto& pmap = *segment.find_or_construct<Map<int, Order>>("MySHMMapName")(segment.get_segment_manager());

        if (pmap.empty()) {
            std::cout << "Inserting data\n";
            auto insert = [&pmap](int i, auto&& s) {
                using namespace std;
                pmap.emplace(piecewise_construct, tie(i), tie(i, s));
            };

            insert(1, "one");
            insert(2, "two");
            insert(3, "three");
        } else {
            std::cout << "Existing data:\n";
            for (auto& [k,v] : pmap) {
                std::cout << k << " " << v.i << " " << v.s << "\n";
            }
        }
    } catch (std::exception &e) {
        std::cout << " error  " << e.what() << std::endl;
        bip::shared_memory_object::remove("095540a3-ceaa-4431-828d-df21d5e384ae");
    }
}

, Map<int, Order>: , , Order.

1: Map<int, String>

Map<int, String> ( std::piecewise_construct):

Live On Coliru

auto& pmap = *segment.find_or_construct<Map<int, String>>("MySHMMapName")(segment.get_segment_manager());

if (pmap.empty()) {
    std::cout << "Inserting data\n";

    pmap.emplace(1, "one");
    pmap.emplace(2, "two");
    pmap.emplace(3, "three");
}

2: Multi Index

Multi-Index, Order :

Live On Coliru

namespace bmi = boost::multi_index;
using Table = bmi::multi_index_container<Order,
    bmi::indexed_by<
        bmi::ordered_unique< bmi::member<Order, int, &Order::i> >
    >,
    Alloc<Order>
>;

, Multi Index , :

if (pmap.empty()) {
    std::cout << "Inserting data\n";

    pmap.emplace(1, "one", pmap.get_allocator());
    pmap.emplace(2, "two", pmap.get_allocator());
    pmap.emplace(3, "three", pmap.get_allocator());
} else {
    std::cout << "Existing data:\n";
    for (Order const& o : pmap) {
        std::cout << o.i << " " << o.s << "\n";
    }

    // demonstrate lookup:
    std::cout << "Finding element 2:" << pmap.find(2)->s << "\n";
}

Existing data:
1 one
2 two
3 three
Finding element 2:two

¹, Coliru. 1- .

+3

But for some reason, the client’s executable generates a segmentation error if I try to access a string, and not by swimming or an integer in the client.

It looks like you are using a std::stringshared memory card in your structure. You cannot do this, because it std::stringallocates its own memory, which goes beyond the scope with boost::interprocess. You should try using a type boost::interprocess::basic_stringinstead std::string. An example of using this in an interprocess card in the Boost documentation

#include <boost/interprocess/containers/string.hpp>
+2
source

Source: https://habr.com/ru/post/1693337/


All Articles