Reputation: 73
I am trying to create a shared memory segment containing three integers and an array. The segment is created and a pointer is attached, but when I try to access the values of the variables (whether changing, printing, etc.) I get a segmentation fault.
Here is the code I tried:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#define SIZE 10
int* shm_front;
int* shm_end;
int* shm_count;
int* shm_array;
int shm_size = 3*sizeof(int) + sizeof(int[SIZE]);
int main(int argc, char* argsv[])
{
int shmid;
//create shared memory segment
if((shmid = shmget(IPC_PRIVATE, shm_size, 0644)) == -1)
{
printf("error in shmget");
exit(1);
}
//obtain the pointer to the segment
if((shm_front = (int*)shmat(shmid, (void *)0, 0)) == (void *)-1)
{
printf("error in shmat");
exit(1);
}
//move down the segment to set the other pointers
shm_end = shm_front + 1;
shm_count = shm_front + 2;
shm_array = shm_front + 3;
//tests on shm
*shm_end = 10; //gives segmentation fault
printf("\n%d", *shm_end); //gives segmentation fault
//clean-up
//get rid of shared memory
shmdt(shm_front);
shmctl(shmid, IPC_RMID, NULL);
printf("\n\n");
return 0;
}
I tried accessing the shared memory by dereferencing the pointer to the struct, but got a segmentation fault each time.
Thanks everyone, no segmentation faults now.
Upvotes: 2
Views: 7186
Reputation: 67695
In your code, you didn't include sys/shm.h
, which should cause your compiler to spit out these:
warning: implicit declaration of function ‘shmget’
warning: implicit declaration of function ‘shmat’
warning: implicit declaration of function ‘shmdt’
warning: implicit declaration of function ‘shmctl’
Casting the return value of shmat
to an int *
will also hide this warning:
warning: assignment makes pointer from integer without a cast
What may happen here is that since the shmat
isn't defined, the compiler will implicitly have it return an int
instead of a void *
. If the address returned by it doesn't fit in a signed integer, you'll get a integer overflow which is undefined behavior, and will most likely cause a segmentation fault for accessing an unallocated memory location.
You shouldn't cast the return value of a function returning void *
specifically to catch those errors (and always compile with warnings enabled, too).
Upvotes: 2
Reputation: 78903
I don't know if this is your only problem but this line
int shm_size = 3*sizeof(int) + sizeof(shm_array[SIZE]);
most probably does not what you want. sizeof(shm_array[SIZE])
is just the size of an int
and not of an array. If you want that you should use sizeof(int[SIZE])
.
And generally I find the modern interface for shared segments, shm_open
, much easier to use. It works analogous to file opening and mapping and has less contraints about segment sizes.
Upvotes: 1
Reputation: 10184
This was really intended as a refinement question, but the formatter blew it up and made it unreadable, so I'm moving it to an answer...
Maybe I'm just looking at this askance, but wouldn't your pointers be as follows:
shm_end = shm_front;
shm_count=shm_front+1
shm_array=shm_front+2;
The first integer would be stored at the head of the block, right at shm_front, and then so on down the line...Unless the shared memory block contains some relevant info at offset 0, I don't know why you would offset these by one each...just an observation.
Upvotes: 0