user1723361
user1723361

Reputation: 73

How to access variables in shared memory

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

Answers (3)

netcoder
netcoder

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

Jens Gustedt
Jens Gustedt

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

David W
David W

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

Related Questions