Search code examples
c++winapifile-mappingfilemap

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


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?


Solution

  • 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.