views:

55

answers:

1

Hi, I'm trying to understand how boost interprocess library works. I have an Equipment class which holds integer values in a vector container.

In parent parent process; I constructed Equipment object in MySegmentObject segment, and in the constructor of this object I created the vector in MySegmentVector segment.

Using child process; I want to access the created object and get the size of the vector. I can access the object using segment->find method but, when I call the getSize() method from the accessed object, it crashes!

What am I doing wrong, probably I'm missing sth about shared memory concept.

I tested the code on Visual Studio 2010 & boost 1.43.0 lib

Equipments.h

#pragma once
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>

using namespace boost::interprocess;

typedef boost::interprocess::allocator<int, managed_shared_memory::segment_manager>     ShmemAllocator; 
typedef boost::container::vector<int, ShmemAllocator> EqVector;

class Equipments { 
public:     
    Equipments(void);   
    ~Equipments(void);  
    void addEquipment(int n);   
    int getSize();  
    int getElement(int n);

private:
    const ShmemAllocator *alloc_inst;
    <offset_ptr>EqVector eqVector;
    managed_shared_memory *segment;
};

Equipments.cpp

#include "StdAfx.h"
#include "Equipments.h"
#include <iostream>

Equipments::Equipments(void)
{   
    shared_memory_object::remove("mySegmentVector"); 
    segment = new managed_shared_memory(create_only, "mySegmentObjectVector", 65536);
    alloc_inst = new ShmemAllocator(segment->get_segment_manager());
    eqVector = segment->construct<EqVector>("myVector")(*alloc_inst);
}


Equipments::~Equipments(void)
{
}

void Equipments::addEquipment(int n)
{
    eqVector->push_back(n);
}

int Equipments::getSize()
{
    return eqVector->size();
}

int Equipments::getElement(int n)
{
    return eqVector->at(n);
}

Main.cpp

#include "stdafx.h"
#include "Equipments.h"
#include <iostream>
#include <string>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>

using namespace boost::interprocess;

int main(int argc, char *argv[]) 
{
    if (argc == 1) 
    {
        std::cout << "parent process" << std::endl;
        shared_memory_object::remove("mySegmentObject"); 
        managed_shared_memory segment(create_only, "mySegmentObject", 65536);
        Equipments *eqPtr = segment.construct<Equipments>("EQ")();

        eqPtr->addEquipment(19);
        eqPtr->addEquipment(12);

        //Launch child process
        std::string s(argv[0]); s += " child ";
        if(0 != std::system(s.c_str()))
            return 1;        //Launch child process
    }
    else 
    {
        std::cout << "child process" << std::endl;
        managed_shared_memory *segment = new managed_shared_memory(open_only, "mySegmentObject");
        std::pair<Equipments*, std::size_t> p = segment->find<Equipments>("EQ");

        if (p.first) 
        {
            std::cout << "EQ found" << std::endl;       
       std::cout << p.first->getSize() << std::endl;       
        }
        else 
        {
            std::cout << "EQ not found" << std::endl;
        }
    }
}
+3  A: 

The problem is that you are using a normal pointer to store your EqVector. When you map a shared memory segment, it maybe mapped into any location in the process's address space. This means that where eqVector is stored in memory is different in the first process' memory space than in the second process'. You need to use a boost::offset_ptr, which stores addresses as offsets from the beginning of shared memory segments, see here: http://www.boost.org/doc/libs/1_35_0/doc/html/interprocess/offset_ptr.html

Joseph Garvin
+1 for going above and beyond the call of duty, subject to this working out.
Steve Townsend
Actually i can access the vector by find method also, bu t i want to access via pointer.
penguru
Err, the way you've edited your code isn't valid syntax, I don't see how that could compile. You want boost::offset_ptr<EqVector>, not <offset_ptr>EqVector.
Joseph Garvin