2

i have a problem with my current project.

Here my header:

#define SHARED_MEMORY_NAME "/osmpmemory"
#define OSMP_MAX_MESSAGES_PROC 16
#define OSMP_MAX_SLOTS 256
#define OSMP_MAX_PAYLOAD_LENGTH 128

typedef struct {
        char msg[OSMP_MAX_PAYLOAD_LENGTH];
    } osmp_msg;

typedef struct {
        size_t memory_size;
        int process_count;
        osmp_msg slots[OSMP_MAX_SLOTS];
    } shm_conf;

And here my code:

shm_conf* memory_conf;
size_t shm_size =  sizeof(shm_conf) + sizeof(int[count][2]) + sizeof(osmp_msg[count][OSMP_MAX_MESSAGES_PROC]);
int fd;

if((fd = shm_open(SHARED_MEMORY_NAME, O_CREAT | O_RDWR, 0640)) == -1) {
        return -1;
    }

if(ftruncate(fd, shm_size) == -1) {
        printf("%s\n", strerror(errno));
        return -1;
    }


if((memory_conf = (shm_conf*)mmap(NULL, shm_size , PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
        printf("%s\n", strerror(errno));
        return 0;
    }

memory_conf->process_count = count;
memory_conf->memory_size = shm_size;

int process_numbers[memory_conf->process_count][2];

for(int i = 0; i < memory_conf->process_count; i++) {
        process_numbers[i][0] = 0;
        process_numbers[i][1] = i;
    }

memcpy(memory_conf + sizeof(shm_conf), process_numbers, sizeof(process_numbers));

I want to store a two dimensional array after the shm_conf struct. But memcpy gives me a segmentation fault and i don't know why, can you help me?

After this array i want store another array, this is why shm_size is bigger than i need currently.

Basti G.
  • 411
  • 1
  • 5
  • 26
  • Idea: Size and offset calculations tend to be error prone, perhaps here too? IDK, yet instead of `shm_conf* memory_conf; size_t shm_size = sizeof(...`, consider `struct { shm_conf memory_conf; int pn[count][2]; osmp_msg[count][OSMP_MAX_MESSAGES_PROC] } m; hm_size = sizeof m;` and use `struct` members: `memcpy(&m.pn, process_numbers, sizeof m.pn);` etc. – chux - Reinstate Monica May 03 '18 at 13:55
  • I can't define the `int pn[count][2]` array inside the struct because the variable `code` isn't known in the struct – Basti G. May 03 '18 at 14:02
  • Yes of course you are correct. Yet with memory re-org, if possible, the scalable part of memory needs can be put to the end of the array such as `typedef struct { int pn[2]; shm_conf c; } i_shm_conf; void fooo(int count) { struct asdf { shm_conf memory_conf; i_shm_conf is[]; } m; size_t sz = sizeof m + sizeof m.is[0] * count; }` which uses a [flexible array member](https://stackoverflow.com/a/32311914/2410359). This also avoids alignment issues your computed approach may have. – chux - Reinstate Monica May 03 '18 at 14:24

1 Answers1

3

The error may be the pointer arithmetic in the memcpy call.

memcpy(memory_conf + sizeof(shm_conf), process_numbers, sizeof(process_numbers));

memory_conf is already an shm_conf pointer so it increments by sizeof(shm_conf). That line should be changed to:

memcpy(memory_conf + 1, process_numbers, sizeof(process_numbers));

To avoid copying into memory that's not been allocated

Joel
  • 348
  • 2
  • 9
  • Yes, thanks, its works fine! :) But how can i change the array in the shared memory? This type casting doesn't work: `int proc_nr[count][2] = (int[][])(memory_conf + 1);` – Basti G. May 03 '18 at 14:28
  • @BastiG. To my knowledge C doesn't allow you to cast to array types at all, but, you could do something like `int proc_nr[count][2];` then `memcpy(&proc_nr, memory_conf + 1, sizeof(int[count][2]);` That should put the integer values in the array – Joel May 03 '18 at 14:47
  • Yes, but if i do this, the values in the shared memory doesn't change... – Basti G. May 03 '18 at 14:49
  • @BastiG. If you want changes to the `proc_nr` variable to change the values in the shared memory you would want something along the lines of `int (*proc_nr)[count][2] = (memory_conf + 1);` then you can make changes to the array pointed to by `proc_nr` (the shared memory) as `(*proc_nr)[0][0] = 0;` – Joel May 03 '18 at 14:55
  • Thanks! I have a last question. I get a `initialization from incompatible pointer type` warning for this assignment `(*proc_nr)[count][2] = (memory_conf + 1);`. There are a option without a warning? – Basti G. May 03 '18 at 15:47
  • @BastiG. Depending on your compiler settings you might be able to get rid of the warning by casting `memory_conf` to a "generic" (`void`) type before storing to an `int[][]` pointer type. Changing the initialization line to `int (*proc_nr)[count][2] = (void*)(memory_conf + 1);`. – Joel May 03 '18 at 16:01
  • Thanks. Know i want to store another array after this int array but i have the same problem like at the start. I try to copy at the new address with that calculation: `memcpy((memory_conf + 1 + (sizeof(int) * process_numbers * 2)), mailbox, sizeof(mailbox));` and the array is this: `osmp_msg mailbox[process_numbers][OSMP_MAX_MESSAGES_PROC];` – Basti G. May 03 '18 at 17:11
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/170313/discussion-between-joel-and-basti-g). – Joel May 03 '18 at 18:23