How to send vector<vector<type>> via MapViewOfFile

831 views Asked by At

I have the following code in a parent process:

vector<vector<double> > matrix(n); /* matrix NxM */
/* pushing data */
HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE,
    0, PAGE_READWRITE, 0, 2*sizeof(int) + sizeof(double)*n*m, lpName);

LPVOID lp = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0);

mat_tmp* tmp = (mat_tmp*)lp;
tmp->n = n; tmp->m = m;
tmp->vv = vector<vector<double> >(matrix.begin(), matrix.end());

In a child process I'm trying to receive this vector >, but my child process terminate every time.

LPTSTR lpName = _tcsdup(TEXT(map_name));
HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE,
    0, PAGE_READWRITE, 0, 2*sizeof(int) + sizeof(double)*n*m, lpName);
LPVOID lp = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0);

mat_tmp * tmp = (mat_tmp*)lp;
vector<vector<double> > matrix(tmp->vv.begin(), tmp->vv.end());

Error occurs when I'm trying to use data from matrix in child process. And the little struct is following:

struct mat_tmp
{
    int n; int m; vector<vector<double> > vv;
};

How can I receive my vector correctly in a child?

3

There are 3 answers

5
Pete On BEST ANSWER

Its not going to work the way you are doing it at the moment. The mapped memory will contain n & m and the internal structure of the vector class which will probably be a couple of pointers, depending on your STL implementation. Followed by a load of junk. You'll not be able to safely access these pointers from the other process as it is in a different address space.

You need to actually copy the memory pointed to by the vector into the mapped memory and reconstruct the vector on the other side.

Additionally the size of the memory you need is not going to be sizeof(int)*n*m. It looks like you want to have 2 ints n & m in the structure and an collection of n*m doubles.

So, allocate 2*sizeof(int) + n*m*sizeof(double). Copy n & m into the memory and then copy the rows of the matrix in. On the receiving side, read n & m and then deserialize the data into your vector of vectors.

Maybe make the struct like this:

struct mat_tmp
{
    int n; int m; double vv[1];
};

Then, copy directly into the shared memory:

double* dst = tmp.vv;
for (size_t y = 0; y < matrix.size(); ++y) {
   memcpy(dst, &(matrix[y][0]), matrix[y].size()*sizeof(double));
   dst += matrix[y].size();
}

On the other side,

dst_matrix.resize(n);
for (size_t y = 0; y < n; ++y) {
    dst_matrix[y].resize(m);
    memcpy(&(dst_matrix[y][0]), tmp + (y * m), m * sizeof(double));
}

All untested and could be made more optimal but hopefully it explains better what you need to do.

0
Jason On

You need to override the default allocator object for the vector to so that it works entirely in the memory space of the MapView, since the default allocator object will use heap memory for all allocations. There is a very old Dr.Dobbs article that Bjarne Stroustrup (creator of C++) wrote that tells exactly how to accomplish this task:

http://www.drdobbs.com/creating-stl-containers-in-shared-memory/184401639

0
Tannin On

This won't work, the vector will only hold a pointer, the actual data is heap-allocated. Your memcpy only copies the pointer, which is invalid on the side of the recipient.