It seems you are on the right way. Here are some tips that may help to avoid common pitfalls.
1) Check return status and error message (if exists) every time you invoke a shared memory function (include errno.h to your code). In case of shmat it could be:
shm = shmat(shmid, 0, 0);
if(shm == (void*)-1)
{
printf("error=%s\n", strerror(errno));
shmctl(shmid, IPC_RMID, NULL);
}
2) Inspect the shared memory on your machine using the ipcs -m utility. You have wrote: "I only managed to use shmget. shmat always causes error for me". Looking at the utility output, especially at the OUTPUT column, you may get some hints, insufficient permissions of the created memory, for example, as for michaelg owner in the following snapshot:
T ID KEY MODE OWNER GROUP
m 922746941 0x330846 ----------- michaelg other
m 788529252 0x100b11c --rw------- sybase12 other
3) Create shared memory with suitable permissions. When you pass the IPC_CREAT flag only to the shmget function, you create memory "without permissions", nobody can attach this segment. Try to give more permissions. The following flag should create a segment with read and write permissions for every process owned by the current user.
shmflg=IPC_CREAT|S_IRUSR|S_IWUSR;
4) Once allocated, the shared memory segment must be explicitly removed from the system when it is not needed. It should be done by shmctl function. Take into consideration, that the function does not remove the segment immediately, it only remarks it as a candidate for removing, the kernel removes it when the segment is not attached to any process. Again inspect the memory with ipcs -m after all your processes terminate. If you still see your shared memory segments, you probably need to review your code again and to add more shmctl deleting the segment. A shared memory segment can be removed from the machine by the ipcrm command (see manual for the arguments, they may differ on different systems).
shmctl(seg_id, IPC_RMID, NULL);