0

I am trying to understand why this simple code leads to a segmentation fault when I try to copy some characters into shared memory using strcpy:

#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>

int main()
{
    key_t key;
    int flag,id;
    char *buf;

    flag=IPC_CREAT|0600;
    if((key=ftok("myfile",12)) == -1 ) {
        perror("key");
        exit(2);
    }   
    printf("%X\n",key);

    if( (id=shmget(key,512,flag)) < 0) exit(1); 

    if( (buf=shmat(id,0,0)) < 0) exit(2);

    printf("PID %d, buf=%p\n",getpid(),buf);
    system("ipcs -m | grep 512");
    sleep(20);

    strcpy(buf,"Hello");
    sleep(100); 
    shmdt(buf);
    exit(0);
}

And here is what I get:

C1A0DAB
PID 12063, buf=0xffffffff8bc78000
0x0c1a0dab 271941746  username      600        512        1
Segmentation fault (core dumped)

Moreover pmap of the process indicates :

00007f778bc78000      4K rw-s-    [ shmid=0x10358072 ]

I guess something's wrong with pointer buf but I don't know how to correct this so far.

Any ideas?

Mat
  • 202,337
  • 40
  • 393
  • 406
IbliSS
  • 25
  • 1
  • 7
  • for shared memory, the code needs: #include and #include – user3629249 Jan 09 '15 at 17:11
  • this: '#include ' is for inter process communication, not shared memory. this: '#include ' is for semaphores, not shared memory – user3629249 Jan 09 '15 at 17:14
  • without the proper #include statements, this code causes the compiler to raise 17 warnings. (and warnings need to be corrected) BTW: when linking, are the correct libraries being accessed? – user3629249 Jan 09 '15 at 17:24
  • need #include for printf() etc. need #include for getpid() and sleep() – user3629249 Jan 09 '15 at 17:35
  • one of the files (sys/shm.h??) includes sys/ipc.h and compiling using that header file needs to have the following statement placed before the #include: '#define _XOPEN_SOURCE' or '#define _SVID_SOURCE' – user3629249 Jan 09 '15 at 17:43
  • this line: 'if( (buf=shmat(id,0,0)) < 0) exit(2);' is comparing a pointer to an integer and a pointer cannot be less than 0 however, the code could use: 'if( (buf=shmat(id,0,0)) == (void*)-1) exit(2);' – user3629249 Jan 09 '15 at 17:51

3 Answers3

2

Please compile with all warnings enabled (at least -Wall for gcc and clang for instance).

You're missing #include <sys/shm.h>, so your compiler assumes that smhat returns an int, when it in fact returns a void*. If the size of int and void* don't match, you have a problem.

Add that include, add the other ones you're missing too while you're at it, and it should work.

Mat
  • 202,337
  • 40
  • 393
  • 406
1

Pay attention to the warnings you get from the compiler. In particular, you get:

file.c:22:5: warning: implicit declaration of function ‘shmat’ [-Wimplicit-function-declaration]
file.c:22:13: warning: assignment makes pointer from integer without a cast

which tells you what the problem is -- the compiler is assuming that shmat returns a (32-bit) integer, when in fact it returns a (64-bit) pointer. So you lose the top 32 bits of the pointer...

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
0

this info, from http://web.cse.ohio-state.edu/~babic/Sem.shmem.new.pdf needs to be taken into account:

important: Semaphores and shared memories not explicitly removed stay in the system after a process that created them terminates and even when a user logs off.

Since UNIX supports limited number of those resources, it is important to make sure that all created semaphores and shared memories are remo ve before logging off.

The directory /usr/class/cis660 include s the script file rsm .dat that provides convenient way to remove all semaphores and all shared memories at once.

An individual semaphore or shared memo ry may be removed using UNIX command ipcrm –s sem# or ipcrm –m mem# , respectively, where sem# and mem# are obtained from UNIX command ipcs , which lists all semaphores and shared memories

user3629249
  • 16,402
  • 1
  • 16
  • 17