PDA

View Full Version : QSharedMemory and C++ objects



MattPhillips
4th December 2009, 00:39
Hello,

I can get QSharedMemory to work just fine with arrays of ints, but not with a vector, so I'm wondering if anyone knows how to do the latter. Obviously it's simple enough to convert a vector of ints into an array of ints and share that, but I want to be able to share complex C++ classes so I figured I would just try to get it to work with a vector first. Anyway, here's what works:


void MemWriter::Write()
{
int* data = (int*)mem->data(); //'mem' is QSharedMemory, created elsewhere
for (int i=min; i<max+1; ++i)
data[i-min] = i;
}

void MemReader::Read()
{
int* data = (int*)(mem->data()); //'mem' is QSharedMemory, created elsewhere
for (int i=0; i<range; ++i)
qDebug() << data[i];
}

I.e., the the integers 0-9 are just written into the shared memory block and then read out again. MemWriter::Write() and MemReader::Read() are in different processes.

Here's what doesn't work:


void MemWriter::Write()
{
vector<int>* vec = reinterpret_cast< vector<int>* >(mem->data()); //'mem' is QSharedMemory, created elsewhere
for (int i=min; i<max+1; ++i)
vec->push_back(i);
}

void MemReader::Read()
{
vector<int>* data = reinterpret_cast< vector<int>* >(mem->data()); //'mem' is QSharedMemory, created elsewhere
for (vector<int>::iterator it=data->begin(); it!=data->end(); ++it)
qDebug() << *it;
}


This crashes when Read() is called. I've tried a few different variations on this, such as static_cast instead of reinterpret_cast--in that case it crashes/produces undefined behavior during Write(). Am I stuck with C int/double/etc arrays?

Matt

faldzip
4th December 2009, 06:39
And how did you create this 'mem' with std::vector inside?

caduel
4th December 2009, 07:45
QVector (and other C++ objects) contain pointers inside. These pointers are pointers inside the creating process's memory. If you put that in shared memory, the other process's accessing it will try that address - which is invalid (hopefully) for them.

You need either special containers or at least allocators to put containers into shared memory. (See e.g. Boost Interprocess)
Anything without pointers can be used (so no QString, std::string either, for example).

HTH

MattPhillips
4th December 2009, 16:08
Caduel,

Thanks, that was exactly it. Just to convince myself I created two structs,


struct A
{
char ch;
int i;
double d;
};

struct B
{
char ch;
int* i;
double d;
};


and indeed, A worked fine but B did not. Thanks again. Thanks too faldzip for your consideration.

Matt

OverTheOCean
21st November 2010, 17:21
Hey Matts,

did you find a way to share pointers to variables ( i.e. struct B ) ?

thanks,

Michael

wysota
21st November 2010, 17:46
You can't do that.

produktdotestow
22nd November 2010, 15:08
don't exaggerate. probably there are some containers that allow you to share whole objects. just search.

MattPhillips
29th November 2010, 07:42
Hi,

It looks like the Boost IPC library has smart pointers which can be used within a shared memory block.

http://www.boost.org/doc/libs/1_38_0/doc/html/interprocess/quick_guide.html#interprocess.quick_guide.qg_offse t_ptr

But no dice with standard containers, in STL or I presume Qt as well.

Matt