2

I am implementing IPC using shared memory in C linux. Here is my receiving process. It's receiving correct length but not the message. However sending process is properly sending it. Please see this and let me know the error.

//header files
#include "/home/user/msgbuf.h"
#define SHMSZ    127
int main()
{
    int shmid;
    key_t key;
    message_buf *rbuf;
    rbuf=malloc(sizeof(*rbuf));
    key = ftok("/home/user/shmem",17);

    if ((shmid = shmget(key, SHMSZ, 0666)) < 0)
    {       perror("shmget");
            exit(1);
    }
    printf("\nShared Memory Id = %d\n",shmid);
    if ((rbuf = shmat(shmid, NULL, 0)) == (message_buf *) -1)
    {       perror("shmat");
            exit(1);
    }
    printf("\nMEMORY SEGMENT ATTACHED TO THE CLIENT'S PROCESS\n");

/* Now read what the server put in the memory */
    printf("\nmsglen = %d",rbuf->msglen);  //this is correct
    rbuf->cp=malloc(rbuf->msglen);
    memcpy(&rbuf->cp,rbuf+sizeof(int),sizeof(*rbuf));
    printf("\nMESSAGE :: %s",rbuf->cp); //MESSAGE :: null
    fflush(stdout);
    shmdt(&shmid);
    printf("\nMEMORY SEGMENT %d DETACHED\n",shmid);
    return 0;
}

msgbuf.h is

typedef struct msgbuf1
{
    int msglen;
    char *cp;
}message_buf;

thanks :)

user3392539
  • 71
  • 1
  • 2
  • 11
  • Deer Ghost-downvoter: explain why. – nouney Mar 31 '14 at 11:33
  • What's this supposed to do: `memcpy(&rbuf->cp,rbuf+sizeof(int),rbuf->msglen);` ? Where have your server placed the message you want to receive ? – nos Mar 31 '14 at 11:35
  • **(m = shmat(shmid, NULL, 0)) == (message_buf *) -1** where m is a ptr to msg_buf. and then m->cp="message entered by user". Also I have changed **rbuf->msglen** to sizeof(*rbuf) to get the ptr to cp. – user3392539 Mar 31 '14 at 11:41
  • @user3392539 You overwrite `cp` in `rbuf->cp=malloc(rbuf->msglen);` so surely you cannot expect that pointer to contain the message anymore. Moreover, pointers are local to a process, you can't transfer a pointer across shared memory, as a pointer is only valid in the process that created it. – nos Mar 31 '14 at 13:03

2 Answers2

5

You read a char* from the shared memory region. However, that points to a buffer allocated with malloc, in the remote process. As such it points to the process heap of local to that other process.

This is simply undefined behaviour.

Instead, make the character buffer part of the shared memory data structure:

//header files
#define MAX_SH_BUFSIZE 1024
//
typedef struct msgbuf1
{
    int msglen;
    char cp[MAX_SH_BUFSIZE];
} message_buf;
sehe
  • 374,641
  • 47
  • 450
  • 633
  • can't I make it dynamic. I mean using *cp instead of character array. and that's why I used memcpy in my prog above – user3392539 Mar 31 '14 at 11:47
  • No. As he said, the buffer returned by malloc is private to the process that called it. – Jonathon Reinhart Mar 31 '14 at 11:55
  • 1
    @JonathonReinhart to me that doesn't make much sense. Why would he be sharing opaque pointers that don't refer to same process space? Also, he's calling memcpy on the stuff. So either it is this (as I describe in my answer) or the OP is completely confused as to what a struct layout is and how the `cp` member functions. The more I look at the code I think it's both – sehe Mar 31 '14 at 11:59
  • Sorry, I was actually replying to the OP in that comment. – Jonathon Reinhart Mar 31 '14 at 12:02
  • @sehe I want cp a ptr. Could you please suggest me what changes I need to make to my code?? Thanks – user3392539 Mar 31 '14 at 12:16
  • Also I am using rbuf=shmat(). Doesn't it mean that rbuf will get address of shared memory segment and hence both processes pointing to same location. I am a beginner so please explain. :) – user3392539 Mar 31 '14 at 12:20
  • 1
    Yes it does. And your struct contains exactly two elements: `msglen` and `cp` whose value will be physically located in that segment. HOWEVER, `cp` _points_ to an address outside that area. Of course, we can't see the 'server' side of the code, so it is "possible" that you store something else entirely, but `char*` suggests that `cp` is intended to contain a _pointer to character_. So your problem is that you have _two_ pointers, and you're only taking care of the one) – sehe Mar 31 '14 at 12:24
  • @user3392539 can you explain why do you want to send a pointer via shm IPC? Perhaps you want to send an arbitrary length string or a linked list? But did you know most full-fledged IPC libraries do "serialization" first? – nodakai Mar 31 '14 at 13:34
0

The problem is with the malloc. malloc addresses have scope till he process not the shared memory. You should not use malloc in shared memory.

Method 1.

Instead use a fix size character array as below:

typedef struct msgbuf1
{
    int msglen;
    char cp[MESSAGE_SIZE];
}message_buf;

Set MESSAGE_SIZE as the maximum size of data you would require.

Method 2. Create a sufficient size shared memory. Make you own malloc and free function which would provide memory from shared memory as and when require. For this you need to keep track of free list, which store the free memory space in the shared memory.

You can divide your shared memory into chunks of like say 256bytes, 512bytes and 1024bytes. Now whenever you require memory the custom malloc function for shared memory shoud hold the logic to provide memory efficiently.

Custom free function would free the shared memory released by program along with adding that chunk(s) in free list

Mohit Jain
  • 270
  • 2
  • 6