Pointers inside shared memory segment

11,566

Solution 1

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

Solution 2

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.

Share:
11,566
Knudow
Author by

Knudow

Updated on June 29, 2022

Comments

  • Knudow
    Knudow almost 2 years

    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)