У меня есть следующий код в родительском процессе:
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());
В дочернем процессе я пытаюсь получить этот вектор>, но мой дочерний процесс завершается каждый раз.
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());
Ошибка возникает, когда я пытаюсь использовать данные из matrix
в дочернем процессе.
И маленькая структура выглядит следующим образом:
struct mat_tmp
{
int n; int m; vector<vector<double> > vv;
};
Как правильно получить мой вектор у ребенка?
Это не сработает так, как вы делаете это в данный момент. Отображенная память будет содержать n & m и внутренняя структура векторного класса, который, вероятно, будет парой указателей, в зависимости от вашей реализации STL. Вслед за грузом мусора. Вы не сможете безопасно получить доступ к этим указателям из другого процесса, так как он находится в другом адресном пространстве.
Вам необходимо скопировать память, на которую указывает вектор, в отображенную память и восстановить вектор на другой стороне.
Кроме того, размер памяти, который вам нужен, не будет sizeof (int) * n * m. Похоже, вы хотите иметь 2 целых & м в структуре и коллекции п * м удваивается.
Итак, выделите 2 * sizeof (int) + n * m * sizeof (double). Скопируйте n & м в память, а затем скопировать строки матрицы в.
На принимающей стороне прочитайте n & м, а затем десериализовать данные в ваш вектор векторов.
Может быть, сделать структуру так:
struct mat_tmp
{
int n; int m; double vv[1];
};
Затем скопируйте непосредственно в общую память:
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();
}
На другой стороне,
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));
}
Все не проверено и может быть сделано более оптимальным, но, надеюсь, это лучше объясняет, что вам нужно делать.
Вам необходимо переопределить объект-распределитель по умолчанию для вектора, чтобы он работал полностью в пространстве памяти MapView, поскольку объект-распределитель по умолчанию будет использовать память кучи для всех распределений. Есть очень старая статья Dr.Dobbs, написанная Бьярном Страуструпом (создателем C ++), в которой рассказывается, как именно выполнить эту задачу:
http://www.drdobbs.com/creating-stl-containers-in-shared-memory/184401639
Это не сработает, вектор будет содержать только указатель, фактические данные размещаются в куче. Ваш memcpy только копирует указатель, который недопустим на стороне получателя.