Можно ли назначить адрес разделяемой памяти указателю напрямую? - PullRequest
0 голосов
/ 20 сентября 2018

Я пытаюсь создать общую память для IPC.Я хочу поместить структуру с динамическим 2D-массивом в нее в общую память.Вот структура.

/* struct with 2 2D arrays. */
struct _test {
    uint16_t **A;
    uint16_t **B;
} test;

Я знаю, что двойной указатель на самом деле не является двумерным массивом, и я должен использовать указатель на массив , как int (*ptr)[3], но проблема в том, чтоЯ могу получить размер 2D-массива только во время выполнения.Таким образом, я должен объявить 2D-массив таким образом (по крайней мере, из того, что я знаю).

Затем я вычисляю размер этих двух массивов во время выполнения, скажем, что они являются массивами 2x2, что занимает 16 байтов (значение uint16_t составляет 2 байта).Итак, я сделал это:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    size_t size = 16;  //size of two uint16_t 2D arrays.
    key_t key;
    key = ftok("dev/null", 1);
    int s_shm_id = shmget(key, size, IPC_CREAT|0600);  //get 16 bytes of shared memory.
    test *shm = (test*)shmat(s_shm_id,(const void*)0,0);  //attach it.

    //I want pointers in this struct to point at shared memory.
    test *ptr = malloc(sizeof(test));  

    //Array A starts at the beginning of shared memory.
    ptr -> A = (uint16_t **)shm;  //My main confusion is here. Is this right?
    int i;
    for(i=0; i<2; i++)
            ptr->A[i] =(uint16_t *)((uint16_t *)ptr->A + i*2);

    //Array B starts right after A.
    ptr -> B = ptr -> A[i-1] + 2;
    for(i=0; i<2; i++)
            ptr -> B[i] = (uint16_t *)((uint16_t *)ptr->B + i*2);
  }

Я понимаю, что это в основном неправильно, я получил segfault, но как?Для указателя нужен адрес, на который нужно указать, поскольку я уже создал пробел (с помощью shmget), почему я не могу сделать указатель, чтобы указывать на него?Спасибо за любую обратную связь заранее!

1 Ответ

0 голосов
/ 20 сентября 2018

То, что вам нужно, это «зубчатые» или «разбросанные» массивы, а не «линейные» массивы.Разбросанный 2D-массив на самом деле представляет собой не один массив, а массивы 1 + N, где N - это размер 2D-матрицы, к которой вы стремитесь.

Код, который вы показываете, пропускает выделение этого 1 массива внутри "1 + N ".

Если вы успешно выделили достаточно памяти для хранения двух двумерных массивов с размером N, равным uint16_t, то есть 2 * N*N * sizeof (uint16_t) байтов, тогда код для подготовки доступа к этой памяти можетВыглядите так (проверка ошибок не учитывает читабельность):

void * p = ... /* Allocate memory here; does not necessarily needs to be SHM. */

uint16_t ** A = malloc(N * sizeof *A);
for (size_t i = 0; i < N; ++i)
{
  A[i] = ((uint16_t*) p) + i*N;
}

uint16_t ** B = malloc(N * sizeof *B);
for (size_t i = N; i < 2*N; ++i)
{
  B[i - N] = ((uint16_t*) p) + i*N;
}

/* Access A[0 .. N-1][0 .. N-1] and B[0 .. N-1][0 .. N-1] here ... */

Помещение A и B в struct, который, в свою очередь, выделяется динамически, предоставляется вам в качестве упражнения.

Доступ к элементам массивов осуществляется прямо: A[0][0] обращается к 1-му элементу 1-го ряда 1-го массива.

Для ясности тот же код для NxM массивов

uint16_t ** A = malloc(N * sizeof *A);
for (size_t i = 0; i < N; ++i)
{
  A[i] = ((uint16_t*) p) + i*M;
}

uint16_t ** B = malloc(N * sizeof *B);
for (size_t i = N; i < 2*N; ++i)
{
  B[i - N] = ((uint16_t*) p) + i*M;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...