2012-05-27 2 views
5

Я пробовал это в течение нескольких часов, а google - все, что мне нравится, но я схожу с ума.Указатели внутри сегмента разделяемой памяти

У меня есть:-структуру

typedef struct { 
    int rows; 
    int collumns; 
    int* mat; 
    char* IDs_row; 
} mem; 

Я не знаю, что размеры Int * (матрица) и символ * недо позже.

Когда я делаю, я создать общую память, как это:

mem *ctrl; 
int size = (2 + ((i-1)*num_cons))*sizeof(int) + i*26*sizeof(char); //I have the real size now 
shmemid = shmget(KEY, size, IPC_CREAT | 0666); 
if (shmemid < 0) { 
    perror("Ha fallado la creacion de la memoria compartida."); 
    exit(1); 
} 
ctrl = (mem *)shmat(shmemid, 0, 0); 
if (ctrl <= (mem *)(0)) { 
    perror("Ha fallado el acceso a memoria compartida"); 
    exit(2); 
} 

Нет проблем здесь. Затем я даю значение ctrl-> rows и columns и присваиваю 0 всей матрице.

Но после этого я пишу что-то в char * и bam, segmentation fault.

Отладка программы Я видел, что оба указателя, мат и IDs_row, где null. Как предоставить им правильные значения внутри сегмента разделяемой памяти?

Я попытался удалить указатель char *, чтобы дать ему попробовать, а затем ошибка сбоя сегментации была в другой программе, подключенной к указанной общей памяти, и просто проверила значения внутри матрицы (проверка -> строки и -> collumns был успешным)

ответ

5
ctrl = (mem *)shmat(shmemid, 0, 0); 

назначает только действительную память для ctrl указателя, не ctrl->mat или ctrl->IDs_row.

Вы, вероятно, хотите:

mem *ctrl; 
shmemid = shmget(KEY, sizeof(ctrl), IPC_CREAT | 0666); 
//allocate memory for the structure 
ctrl = (mem *)shmat(shmemid, 0, 0); 

//allocate memory for the int* 
shmemid = shmget(KEY,((i-1)*num_cons))*sizeof(int), IPC_CREAT | 0666); 
ctrl->mat = (int*)shmat(shmemid, 0, 0); 

//allocate memory for the char* 
shmemid = shmget(KEY,i*26*sizeof(char), IPC_CREAT | 0666); 
ctrl->IDs_row = (char*)shmat(shmemid,0,0); 
+0

Спасибо! Я никогда не думал о том, чтобы делать shmget для каждого указателя. (Я даже не понимаю, как это работает, делая тот же вызов, но «кастинг») Теперь возникает проблема со вторым целым числом в struct, «collumns». Я помещаю «1» в один процесс, а другой процесс читает его как 62045 или что-то в этом роде. Я попытался изменить sizeof (ctrl) на sizeof (men) и 2 * sizeof (int) + sizeof (int *) + sizeof (char *), но не повезло. – Knudow

+0

Извините, я отправил сообщение, а затем отредактировал его. Можете ли вы мне немного помочь? Теперь у меня есть проблема со вторым целым числом в структуре. – Knudow

+0

@ user1420534, пожалуйста, задайте новый вопрос с этой новой проблемой, они, похоже, не связаны. –

7

Прежде всего, вкладывая абсолютные указателей в общих сегментах памяти страшной terible идея - эти указатели будут действительны только в процессе, заполнивших их значения. Общие сегменты памяти: не гарантируется для присоединения к одному виртуальному адресу в каждом процессе. Напротив - они прикрепляют, где система считает это возможным, когда shmaddr == NULL указан по вызову shmat(). Вы можете указать один и тот же виртуальный адрес при вызове shmat(), но это зависит от вас, чтобы убедиться, что в этой области памяти ничего не отображается в всех участвующих процессов. Это трудно сделать переносимым образом. Что вам больше всего хотелось бы сделать:

1) Выделите один большой сегмент разделяемой памяти, который вмещает как структуру mem, так и два массива данных. Затем вы должны указывать не абсолютные указатели, а указатели относительно начала блока памяти, а затем корректировать их использование.

2) Выделяют три различных сегментов разделяемой памяти, но вместо того, чтобы указатели, положить идентификаторов совместно используемой памяти Для работы , возвращаемый shmget():

typedef struct { 
    int rows; 
    int collumns; 
    int mat_id; 
    int IDs_row_id; 
} mem; 

Если вам необходимо получить доступ к матрице или массив идентификаторов просто присоедините к идентификатору разделяемой памяти, сохраненному в соответствующем поле.

Обратите внимание, что при использовании тех же KEY в последующих вызовах shmget() не ожидается ожидаемого результата, если KEY == IPC_PRIVATE. Лучше всего использовать фиксированное значение ключа для блока разделяемой памяти с дескриптором (типа mem) и IPC_PRIVATE для двух других блоков памяти, иначе три вызова фактически вернут тот же блок разделяемой памяти - первый будет создайте его, а следующие два просто вернут свой идентификатор, так как блок с этим ключом уже существует.