1

I'm following the Linux Programming Interface book (page 1004-1005).

I know the book uses C. But I'd like to implement the same behavior in C++. That is: share a struct between processes through shared memory.

#include <iostream>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>

using namespace std;

struct my_pair {
  int a;
  int b;
};

int main()
{
  key_t key = ftok("aaaaa", 1);
  int shmid = shmget(key, sizeof(my_pair), IPC_CREAT);
  my_pair *numbers;
  numbers = shmat(shmid, NULL, 0);

  cout << numbers->a;

  return 0;
}

It gives me this error:

shteste.cpp: In function 'int main()':

shteste.cpp:18: error: invalid conversion from 'void*' to 'my_pair*'

I understand that C++ is more strict. If I cast the return of shmat to (my_pair *), it compiles but gives me segmentation fault during execution.

Is it possible (how) to use Linux / C shared memory facilities with C++ ?

I'm compiling with: G++ 4.4.7: g++ shteste.cpp -o shteste -std=c++0x

Thanks...

EDIT: Following all sugestions, this is the code now:

int main()
{
 key_t key;

 if ((key = ftok("/home/alunos/scd/g11/aaaaa", 1)) == (key_t) -1) {
   perror("IPC error: ftok"); exit(1);
 }

 int shmid = shmget(key , sizeof(my_pair), IPC_CREAT | 0640);

 if (shmid == -1) {
     perror("Could not get shared memory");
     return EXIT_FAILURE;
 }

 my_pair *numbers;
 void* mem = (my_pair*) shmat(shmid, NULL, 0);
 if (mem == reinterpret_cast<void*>(-1)) {
     perror("Could not get shared memory location");
     return EXIT_FAILURE;
 } else {
     numbers = reinterpret_cast<my_pair*>(mem);
     cout << numbers->a;
 }

 return EXIT_SUCCESS;
}

aaaaa contents: notacat

[scd11@VM11 ~]$ ./shteste

Could not get shared memory: Permission denied

6
  • 1
    Are you sure the error is produced by the code you show? I would expect this error if you didn't have the cast, as in numbers = shmat(...). But the cast should take care of it. Commented Sep 30, 2017 at 17:50
  • You are correct... I copied the "fixed"code... the one which I cast (and, thus, don`t complain about conversion) but get segmentation fault. Commented Sep 30, 2017 at 17:53
  • 2
    You should check return value from shmget and shmat. Commented Sep 30, 2017 at 17:54
  • If I test your code with strace, I got: "64 5327 shmget(0xffffffff, 8, IPC_CREAT|000) = 11534358 65 5327 shmat(11534358, NULL, 0) = -1 EACCES (Permission denied)" Commented Sep 30, 2017 at 17:57
  • C allows casting other pointer types to/from void* implicitly, C++ requires you to cast it. Commented Sep 30, 2017 at 17:58

4 Answers 4

2

This is likely a permissions issue. You can check the return values of shmget and shmat and use perror to print a human-readable error message like this.

#include <iostream>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

struct my_pair {
  int a;
  int b;
};

int main()
{
  key_t key = ftok("aaaaa", 1);
  int shmid = shmget(key, sizeof(my_pair), IPC_CREAT | 0777);
  if (shmid == -1) {
      perror("Could not get shared memory");
      return EXIT_FAILURE;
  }

  my_pair *numbers;
  void* mem = (my_pair*) shmat(shmid, NULL, 0);
  if (mem == reinterpret_cast<void*>(-1)) {
      perror("Could not get shared memory location");
      return EXIT_FAILURE;
  } else {
      numbers = reinterpret_cast<my_pair*>(mem);
      cout << numbers->a;
  }

  return EXIT_SUCCESS;
}
Sign up to request clarification or add additional context in comments.

3 Comments

You are absolutely correct: "Could not get shared memory location: Permission denied". Should I ask the system administrator or there is anything that I, as the user/developer, can do ?
@VictorMarconi: No, you should set the permissions correctly :-) See my answer!
I'd like to thank everyone. All answers helped... the problem was a bit of each. The wrong permission. Therefore, I couldn`t use the same key again (ftok). Thanks a lot.
2

You simple forget to set the permissions:

int shmid = shmget(key, sizeof(my_pair), IPC_CREAT | 0777);

As I already mentioned in my comment, the result of the failing command can be seen with strace.

64 5327 shmget(0xffffffff, 8, IPC_CREAT|000) = 11534358
65 5327 shmat(11534358, NULL, 0) = -1 EACCES (Permission denied)"

If your file "aaaaa" is existing, the code works for me.

Comments

2

This is a permissions issue.

Per the shmget() documentation:

SYNOPSIS

#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

...

DESCRIPTION

...

  • The low-order nine bits of shm_perm.mode are set to the low-order nine bits of shmflg.

You didn't set any permission bits. The low-order nine bits of shmflag in your call are all zero:

int shmid = shmget(key, sizeof(my_pair), IPC_CREAT);

You need to set the proper permissions, something like this:

int shmid = shmget(key, sizeof(my_pair), IPC_CREAT|0640);

You will also likely have to use ipcrm to remove the current shared-memory segment, as it will remain as-is with the incorrect permssions. Even if you change your code, your shmget() calls will return the id of the existing segment - the one that you can't attach because the permissions are missing.

First, use ipcs -a to list the shared memory segments, then use ipcrm -m shmid or ipcrm -M shmkey to remove the segment with incorrect permissions.

1 Comment

I'd like to thank everyone. All answers helped... the problem was a bit of each. The wrong permission. Therefore, I couldn`t use the same key again (ftok). Thanks a lot.
1

According to ftok man page:

The ftok() function uses the identity of the file named by the given
pathname (which must refer to an existing, accessible file).

With existing file your code will work.

Alternatively you can use:

key = IPC_PRIVATE

which will be sufficient for this example, but will not work for real IPC.

1 Comment

I'd like to thank everyone. All answers helped... the problem was a bit of each. The wrong permission. Therefore, I couldn`t use the same key again (ftok). Thanks a lot.

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.