I've spent some time scouring the boost interprocess documentation but I remain stumped by this weird bug. I've seen this code work on boost version 1.42, x86, but not on the versions mentioned in the title.
This is a simple client-server model that shares strings. The server sets up and waits. When the client shares new strings with the server, it prints the newly shared strings. The code is as follows:
Server:
//compile this with: g++ -g server.cc -o server -lrt -lboost_thread-mt -lpthread -lcurses
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cassert>
#include <boost/interprocess/containers/vector.hpp>
#include <iostream>
#include<curses.h>
#include<unistd.h>
using namespace std;
using namespace boost::interprocess;
int main()
{
typedef boost::interprocess::allocator<char, managed_shared_memory::segment_manager> CharAllocator;
typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> opString;
typedef boost::interprocess::allocator<opString, managed_shared_memory::segment_manager> StrAlloc;
typedef vector<opString, StrAlloc> opStringVector;
struct shm_remove
{
shm_remove() { shared_memory_object::remove("opSHM"); }
~shm_remove(){ shared_memory_object::remove("opSHM"); }
} remover;
managed_shared_memory managed_shm(open_or_create, "opSHM", 1000);
CharAllocator charallocator (managed_shm.get_segment_manager());
StrAlloc stralloc(managed_shm.get_segment_manager());
opStringVector * ID_Descript = managed_shm.construct<opStringVector>("ID_DESCRIPTOR")(stralloc);
opStringVector * ID_Handle = managed_shm.construct<opStringVector>("ID_HANDLE")(stralloc);
std::string serD = "This is the server";
std::string serI = "SERVER";
opString st1(charallocator);
opString st2(charallocator);
st1 = serD.c_str();
st2 = serI.c_str();
ID_Descript->push_back(st1);
ID_Handle->push_back(st2);
int i=0;
initscr(); //in ncurses
timeout(0);
int lastSize = 0;//ID_Handle2->size();
printw("\n Registration List: \n");
while(!i)
{
usleep(10000);
i=getch();
if(ID_Handle->size()!=lastSize)
{
for(int j = lastSize;j<ID_Handle->size();j++)
{
const char * hand_st = ID_Handle->at(j).c_str();
const char * desc_st = ID_Descript->at(j).c_str();
std::string hID = hand_st;
std::string dID = desc_st;
std::string newstr = "New process registered: " + hID + "\t" + dID;
const char * st = newstr.c_str();
printw("%s \n",st);
}
lastSize = ID_Handle->size();
}
if(i>0)
i=1;
else
i=0;
}
endwin();
}
Client:
//Compile this with: g++ -g client.cc -o client -lrt -lboost_thread-mt -lpthread -lcurses
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cassert>
#include <boost/interprocess/containers/vector.hpp>
#include <iostream>
#include<curses.h>
#include<unistd.h>
using namespace std;
using namespace boost::interprocess;
int main()
{
typedef boost::interprocess::allocator<char, managed_shared_memory::segment_manager> CharAllocator;
typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> opString;
typedef boost::interprocess::allocator<opString, managed_shared_memory::segment_manager> StrAlloc;
typedef vector<opString, StrAlloc> opStringVector;
managed_shared_memory managed_shm(open_only, "opSHM");
CharAllocator charallocator (managed_shm.get_segment_manager());
StrAlloc stralloc(managed_shm.get_segment_manager());
opStringVector * ID_Descript2 = managed_shm.find<opStringVector>("ID_DESCRIPTOR").first;
opStringVector * ID_Handle2 = managed_shm.find<opStringVector>("ID_HANDLE").first;
opString st1(charallocator);
opString st2(charallocator);
std::string des;
std::string handle;
des = "A Dummy registration";
handle = "DU";
st1 = des.c_str();
st2 = handle.c_str();
ID_Descript2->push_back(st1);
ID_Handle2->push_back(st2);
cout << ID_Descript2->back() << '\t' << ID_Handle2->back() << endl;
des = "Null Algorithm\0";
handle = "OP_NULL";
st1 = des.c_str();
st2 = handle.c_str();
ID_Descript2->push_back(st1);
ID_Handle2->push_back(st2);
cout << ID_Descript2->back() << '\t' << ID_Handle2->back() << endl;
des = "First Algorithm";
handle = "OP_ALG_FIRST";
st1 = des.c_str();
st2 = handle.c_str();
ID_Descript2->push_back(st1);
ID_Handle2->push_back(st2);
cout << ID_Descript2->back() << '\t' << ID_Handle2->back() << endl;
des = "Last Algorithm";
handle = "OP_ALG_LAST";
st1 = des.c_str();
st2 = handle.c_str();
ID_Descript2->push_back(st1);
ID_Handle2->push_back(st2);
cout << ID_Descript2->back() << '\t' << ID_Handle2->back() << endl;
}
This is the Server output:
Registration List:
New process registered: SERVER This is the server
New process registered: DU A Dummy registration
New process registered: OP_NULL Null AlgorithmTver
New process registered: OP_ALG_FIRST First AlgorithmAtion
New process registered: OP_ALG_LAST Last Algorithm
This is the client output:
A Dummy registration DU
Null Algorithm OP_NULL
First Algorithm OP_ALG_FIRST
Last Algorithm OP_ALG_LAST
As you can see, the server get's the string data, but due to incorrect string termination prints extra/overlapping characters in its output (4th and 5th lines). The client side data is uncorrupted. I'm wondering if something else important is not being done. Would appreciate any pointers on this. Also weird how it works on the Boost 1.42 x86 version without any corruption on the server side. Thanks alot!
P.S: As I am using the managed shared memory feature, I did not explicitly use any synchronization (mutex) mechanisms. Do I have to?