14

I've been trying this for hours, and google all the things I kind think of, but I'm going crazy.

I have a struct:

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

I don't know the sizes of the int* (a Matrix) and char* untill later.

When I do, I create the shared memory like this:

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); } 

No problem here. Then I give a value to ctrl->rows and collumns, and assign 0 to all the matrix.

But after that, I write something in the char* and bam, segmentation fault.

Debugging the program I saw that both pointers, mat and IDs_row where null. How do I give them the correct values inside the shared memory segment??

I tried removing the char* pointer, just to give it a try, and then the segmentation fault error was in the other program that connected to said shared memory and just checked the values inside the matrix (checking ->rows and ->collumns was succesfull)

2 Answers 2

15

First of all, putting absolute pointers in shared memory segments is terrible terible idea - those pointers would only be valid in the process that filled in their values. Shared memory segments are not guaranteed to attach at the same virtual address in every process. On the contrary - they attach where the system deems it possible when shmaddr == NULL is specified on call to shmat(). You could specify the same virtual address when calling shmat() but it is up to you to ensure that nothing else is mapped on that memory region in all participating processes. This is hard to do in a portable manner. What you would most like to do is to either:

1) Allocate one big shared memory segment that accomodates both the mem structure and the two data arrays. Then you should put not absolute pointers but rather pointers relative to the beginning of the memory block and then adjust on usage.

2) Allocate three different shared memory segments but instead of putting pointers, put the shared memory IDs as returned by shmget():

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

When you need to access the matrix or the IDs array just attach to the shared memory ID stored in the corresponding field.

Pay attention though that using the same KEY in subsequent invocations of shmget() will not produce the expected result unless KEY == IPC_PRIVATE. It is best to use a the fixed key value for the shared memory block with the descriptor (of type mem) and IPC_PRIVATE for the other two memory blocks otherwise the three calls will actually return the same shared memory block - the first one will create it and the next two will simply return its ID since a block with that key already exists.

Sign up to request clarification or add additional context in comments.

Comments

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

This only assigns valid memory to the ctrl pointer, not to ctrl->mat or ctrl->IDs_row.

You probably want:

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); 

6 Comments

Thank you! I'd never thought of doing the shmget for each pointer. (I don't even understand how that works, doing the same call but "casting" it) Now there is a problem with the second integer in the struct, the "collumns". I put a "1" there in one process, and the other process reads it as 62045 or something like that. I tried changing sizeof(ctrl) to sizeof(men) and 2*sizeof(int)+sizeof(int*)+sizeof(char*), but no luck.
Sorry, i sent the message and then edited it. Can you help me a bit more? I have a problem now with the second integer in the struct.
@user1420534 please post a new question with this new issue, they don't seem related.
ctrl is a pointer. Using sizeof(ctrl) in the first call to shmget() is incorrect, although shared memory blocks always consist of integer number of pages and thus the size is rounded up to a multiple of the page size (at least 4 KiB on x86). Using the same value of KEY three times is also incorrect in that particular case - both mat and IDs_row field will point to the beginning of the same block and writing to any of them will overwrite the structure.
The principle is that one should not put pointers in shared memory at all.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.