0

I have an array in shared memory. I want to use a pointer for iterating through this array, which also is meant to be shared. Here is what I tried:

    /* initialize color sequence in shared memory */
    shmkey = ftok("/dev/null",3);   /* executable name and a random number */
    shmid = shmget(shmkey, sizeof(char), 0700 | IPC_CREAT);
    if(shmid < 0){      /* shared memory error check */
        perror("shmget\n"); 
        exit(1);
    }
    queue = (char*) shmat(shmid, NULL, 0);  /* shared memory part of colorSequence */
    printf("queue allocated.\n");

    /* initialize color sequence pointer in shared memory */
    shmkey = ftok("/dev/null//",61);    /* executable name and a random number */
    shmid = shmget(shmkey, sizeof(char), 0700 | IPC_CREAT);
    if(shmid < 0){      /* shared memory error check */
        perror("shmget\n"); 
        exit(1);
    }
    p = (char*) shmat(shmid, NULL, 0);  /* pointer to queue in shared memory */
    printf("queue pointer allocated.\n");
    p = &queue[0];

Now I fork the child and try to change the value p, but a change made in one process doesn't affect the other.

if(fork() == 0){   /* child process */
    sem_wait(&sem);
    printf("   Child printing *p=%c, p=%p\n",*p,p);
    p++;
    printf("   Child printing after++ p=%c, p=%p\n",*p,p);
    sem_post(&sem);
    exit(0);
}
else{   /* parent process */
    sem_wait(&sem);
    printf("Parent printing *p=%c, p=%p\n",*p,p);
    p+=2;
    printf("Parnet printing after++ p=%c, p=%p\n",*p,p);
    p = NULL;   //even though this, program doesn't fail
    sem_post(&sem);
}

Yet, the output is (Contents of queue is as follows: R B G . . .) :

Parent printing           *p=R, p=0x7f5c77837000
Parnet printing after++   p=B, p=0x7f5c77837002
   Child printing         *p=R, p=0x7f5c77837000
   Child printing after++ p=G, p=0x7f5c77837001

I couldn't figure out why I get these results even though the pointer is supposed to be shared. Can you help me fix this? Thanks.

EDIT

When I try to change the value p points to in parent process, the effects are visible when printing from child process. However incrementing pointer doesn't work.

1
  • You can share memory, but you can't share a pointer. Remember that the (virtual) memory map is unique for each process. A pointer to shared memory in one process may (and most likely will) not be the same as a pointer to the same shared memory in another process. Commented May 5, 2013 at 0:44

1 Answer 1

2

You actually have two problems, but one is mitigated by the operating system.

The first problem is that you say your shared memory is of size 1 (sizeof(char)). This is mitigated by the OS as it rounds it up to page size.

The second problem is this:

p = (char*) shmat(shmid, NULL, 0);  /* pointer to queue in shared memory */

p = &queue[0];

Here you get p from shared memory, the you overwrite this pointer with another pointer.

However, this is a moot problem fro two reasons: The first is the one I commented about. The second is that even if you don't overwrite the pointer p it will still be "local" to your process so doing e.g. p++ will not change the copy in shared memory as the actual pointer isn't shared. If you truly wanted to have a pointer in shared memory you would have p be a pointer to a pointer, would have to do (*p)++ to increase both locally and in the shared memory.

Sign up to request clarification or add additional context in comments.

4 Comments

Does that mean I have to define p as char** and allocate shared memory? And then I do (*p) = &queue[0]. Would that be right? If not, how should I proceed?
I'm not sure putting a memory address into the shared memory segment to be used by another process is safe. Memory is mapped in strange ways (at least to me), and that doesn't seem like a guarantee that should be relied on. You should at least abstract that to an offset into the memory space that would then be used against a local pointer in each copy. But maybe what you say is ok -- still seems scary to me.
@Volkanİlbeyli Yes, thats how you should do it, if a pointer could indeed be shared.
If the second process is a child of the first, and the first creates and attaches to the shared memory before forking, the second process has the shared memory segment at the same address as the first. With System V IPC, you can also request that a shared memory segment is located at a a specific address; if all processes request the same address and none of them is refused, you can use pointers into the shared memory in the different processes. Otherwise (and it is always safe to do this), you should record offsets or index numbers for arrays etc, and use those in the different processes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.