Search code examples
c++boostshared-memoryinterprocessboost-interprocess

problems with boost:interprocess shared memory


I'm having some trouble implementing boost/interprocess library for shared memory operations between two programs. This is the first I've used any shared memory operations, and I have first modified some of the sample code in the boost documentation I found here: (http://www.boost.org/doc/libs/1_41_0/doc/html/interprocess/quick_guide.html).

The modified demo works good, and basically is like this:

typedef std::pair<double, int> MyType;
managed_shared_memory segment(create_only, "MySharedMemory", 65536);

MyType *instance = segment.construct<MyType>
    ("MyType instance")  //name of the object
    (12.34, 0);            //ctor first argument

MyType *instance2 = segment.construct<MyType>
    ("MyType instance2")  //name of the object
    (56.78, 0);            //ctor first argument

And then in a another process, retrieve these variables:

managed_shared_memory segment(open_only, "MySharedMemory");

std::pair<MyType*, managed_shared_memory::size_type> res;
std::pair<MyType*, managed_shared_memory::size_type> res2;

res = segment.find<MyType>("MyType instance");
printf("1: %d, %d\n", res.first, res.second); // show pointer and size
printf("1a: %f\n\n", *res.first); //show double value


res2 = segment.find<MyType>("MyType instance2");
printf("2: %d, %d\n", res2.first, res2.second); // show pointer and size
printf("2a: %f\n", *res2.first); // show double value

ok, so all th at looks ok, and the terminal output is:

1: 196724, 1
1a: 12.340000

2: 196780, 1
2a: 56.780000

The problem is when I try and replicate this in another (existing) application.

I have done everything almost identically as far as I can tell (identically in terms of syntax even maybe?), but am getting some different and unexpected results.

typedef std::pair<double, int> myDouble;
managed_shared_memory segment(create_only, "sharedMemBlock", 65536);

myDouble *valX = segment.construct<myDouble>
    ("valX")
    (1.1, 0);

myDouble *valY = segment.construct<myDouble>
    ("valY")
    (2.2, 0);

myDouble *valZ = segment.construct<myDouble>
    ("valZ")
    (3.3, 0);

and in the second process to retrieve these values:

managed_shared_memory segment(open_only, "sharedMemBlock");
std::pair<myDouble*, managed_shared_memory::size_type> valShrX;
std::pair<myDouble*, managed_shared_memory::size_type> valShrY;
std::pair<myDouble*, managed_shared_memory::size_type> valShrZ;

valShrX = segment.find<myDouble>("valX");
valShrY = segment.find<myDouble>("valY");
valShrZ = segment.find<myDouble>("valZ");

printf("PtrvalSharedX: %d,PtrvalSharedY: %d, PtrvalSharedZ: %d\n", valShrX.first, valShrY.first, valShrZ.first);
printf("valSharedX: %f, valSharedY: %f, valSharedZ: %f\n\n", *valShrX.first, *valShrY.first, *valShrZ.first);

but the results are not what I expect, and are coming out like this:

PtrvalSharedX: 196724, PtrvalSharedY: 196772, PtrvalSharedZ: 196820
valSharedX: 1.100000, valSharedY: 0.000000, valSharedZ: 2.200000

So, what's going on here? Why am I not getting 1.1, 2.2 and 3.3 for valSharedX, valSharedY, and valSharedZ respectively?

Not sure why essentially the same code works in one instance, but not another. I noticed that the difference between pointers in the first example (196780 - 196724) = 56, but is smaller in the second example (196772 - 196724) = (196820 - 196772) = 48. Not sure if that is relevant, but thought it was worth pointing out (pun!).

Thanks, B


Solution

  • The problem that everyone overlooked, including myself, was this...

    because of the type:

    std::pair<myDouble*, managed_shared_memory::size_type> valShrX
    

    getting:

    valShrX.first
    

    returns a pointer to a myDouble, and not to the first double that is a part of the std::pair that is defined in:

    typedef std::pair<double, int> myDouble;
    

    Since printf doesn't know what myDouble type really is, and since that type is not natively known by printf, the issue presented only when printing multiple values in a sequence and relates to the size of myDouble not matching the size of a double.

    So printing each value with its own printf statement (like in the first code excerpt) works fine, because the pointer valShrX.first tells printf where to start correctly. Even though the size of valShrX.first must include the int that is a part of the pair, printf prints the %f and stops.

    In the second code excerpt, I tried printing all three values in shared memory in the same printf statement, and so the full size of std::pair myDouble (including therein the double and the int) was propagated and would offset the second and third values printed.

    The correct statement should get just the first item of the myDouble pair, that is within the parent pair ... In other words this is the correct printf syntax given my data types:

    printf("valSharedX: %f, valSharedY: %f, valSharedZ: %f\n\n", valShrX.first->first, valShrY.first->first, valShrZ.first->first);
    

    So, my printf syntax was incorrect in both examples, but the more punitive operation of printf when printing multiple values in one statement was the only case to make the problem apparent.

    My only remaining question that is tickling my brain is this: Why did this problem present itself in Visual Studio 2013, but the identical code when compiled in Linux did not show the problem when printf's %f received a myDouble in a series of values being printed? It all worked fine when compiled in linux. why?