简体   繁体   中英

Linux shared memory segfault

I have been having difficulties getting a useable shared memory region in a sample C program (RHEL 6). It should be quite basic so I'm not sure what I'm doing wrong but when I allocate the memory region it appears to be accessible initially. However, when I return from an initialization function the memory region is no longer accessible and I get a segfault when I try to access the memory region.

I have tried running it through GDB and all I see is a segfault on the line where I try to do this memcpy:

memcpy(ptr, &x, sizeof(x));

It's probably something minor that I just cannot see for some reason! Thanks.

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <errno.h>


void* shared_mem[2];

int init(int *memAddress);

int main() {

  if(init((int*)&shared_mem[0]) < 0) {
    printf("Error initializing, exiting\n");
    exit(1);
  }

  int *ptr=shared_mem[0];

  int x=278;
  memcpy(ptr, &x, sizeof(x));
  printf("data written to memAddress: %d\n", shared_mem[0]);

}

// Initialize shared memory region and insert test data
int init(int *memAddress) {
    key_t key = 234324;
    int size = sizeof(int);
    static const unsigned int flags = S_IRUSR | S_IWUSR | S_IRGRP |
                                       S_IWGRP | S_IROTH | S_IWOTH | IPC_CREAT;
    int id = shmget(key, size, flags);
    if (id < 0)
    {
        return(-3);
    }
    *memAddress = shmat(id,0,0);
    if ((int)memAddress == -1)
    {
        return(-4);
    }

    int z=123;
    memcpy(memAddress, &z, sizeof(z));
    printf("data written to memAddress: %d\n", memAddress[0]);
    return(0);
}

Something is completely wrong here and it begins with the following line:

int init(int *memAddress)

You pass a pointer to shared_mem to the function "init". Therefore memAddress will point to the 8- or 16-byte (depending on the CPU type) array shared_mem .

*memAddress = shmat(id,0,0);

If sizeof(void *) == sizeof(int) this would work however then you'd have to do other pointer casts. shared_mem[0] will contain a pointer to the memory, casted to int .

If sizeof(void *) != sizeof(int) you'll already have problems here.

(int)memAddress == -1

This will not work in any case:

(int)memAddress is the address of the array shared_mem and not the value returned by shmat .

memcpy(memAddress, &z, sizeof(z));

This will write the value 123 into shared_mem[0] . Therefore the following instruction:

memcpy(ptr, &x, sizeof(x));

... will be equal to:

memcpy((void *)123, &x, sizeof(x));

... which will cause the error.

The correct function would look like this:

int init(void **memAddress) {     // void **
    ...
    *memAddress = shmat(id,0,0);  // This was correct!
    if ((int)(*memAddress) == -1) // Note the "*"
        ...
    memcpy(*memAddress, &z, sizeof(z)); // Note the "*"
}

Your init function isn't modifiying shared_mem with the allocated memory address - the parameter to init() needs to be declared as int **memaddress for example look at your line *memaddress=shmget(...) with parameter defined as int *memaddress this is storing the result of shmget as an integer, that isn't right. You need to check all the related uses of memaddress are correct. You can check this in gdb, look at the result of shmget, make sure that is being stored in shared_mem[0].

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM