A simple C++ shared memory program written on linu

2019-02-21 23:01发布

#include <stdio.h> 
#include <sys/shm.h> 
#include <sys/stat.h> 
#include <string>
#include <vector>
#include <iostream>

using namespace std;

struct LOCK {
  string name;
  string type;
  vector <string> pids;
};

int main () 

{

  int segment_id; 

  LOCK* shared_memory; 

  struct shmid_ds shmbuffer; 

  int segment_size; 

  const int shared_segment_size = 0x6400; 



  /* Allocate a shared memory segment.  */ 

  segment_id = shmget (IPC_PRIVATE, shared_segment_size, 

                     IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); 

  /* Attach the shared memory segment.  */ 

  shared_memory = (LOCK*) shmat (segment_id, 0, 0); 

  printf ("shared memory attached at address %p\n", shared_memory); 

  /* Determine the segment's size. */ 

  shmctl (segment_id, IPC_STAT, &shmbuffer); 

  segment_size  =               shmbuffer.shm_segsz; 

  printf ("segment size: %d\n", segment_size); 

  /* Write a string to the shared memory segment.  */ 

  //sprintf (shared_memory, "Hello, world."); 
  shared_memory -> name = "task 1";
  shared_memory -> type = "read";
  (shared_memory -> pids).push_back("12345");
  (shared_memory -> pids).push_back("67890");

  /* Detach the shared memory segment.  */ 

  shmdt (shared_memory); 



  /* Reattach the shared memory segment, at a different address.  */ 

  shared_memory = (LOCK*) shmat (segment_id, (void*) 0x5000000, 0); 

  printf ("shared memory reattached at address %p\n", shared_memory); 

  /* Print out the string from shared memory.  */ 

  //printf ("%s\n", shared_memory -> name); 
  cout << "Name of the shared memory: " + shared_memory -> name << endl;

  /* Detach the shared memory segment.  */ 

  shmdt (shared_memory); 



  /* Deallocate the shared memory segment.  */ 

  shmctl (segment_id, IPC_RMID, 0); 



  return 0; 

} 

I got the code from a tutorial on shared memory. It worked until I defined struct LOCK and tried to write LOCKs instead of char* into the shared memory.

Could someone please help me figure out the problem here that causes the segmentation fault?

3条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-02-21 23:25

You are placing vectors and strings into shared memory. Both those classes allocate memory of their own, which will be allocated within the address space of whatever process generates the allocation, and will produce a segfault when accessed from the other process. You could try specifying allocators to use that shared memory, but since in C++03 allocators are assumed to be stateless I'm not sure if it will be possible.

Consider checking out how Boost.Interprocess does it.

查看更多
相关推荐>>
3楼-- · 2019-02-21 23:26

I know it is very long time ago. But I was searching how-to (remember) about shared mem and this thread is interesting.

My Two cents to the demander :

  • Please consider that reading and writing to SharedMemory is exactly like reading and writing into a FileSystem.
  • Shared Memory ID == file_handle from open(...);

    So... How do you CORRECTLY serialize and then read-write std::string or even std::vector into a FILE ? Do you really 'expand/shrink' a std::string or std::vector from within a FILE ??

Thank you :)

查看更多
smile是对你的礼貌
4楼-- · 2019-02-21 23:36

You have a number of problems. The obvious one is that you don't construct your object. In opaque form, you are currently doing:

class Foo;

Foo * p = get_memory();

p->bar = 5;  // ouch!

What you should be doing, at the very least:

void * addr = get_memory(sizeof(Foo));
Foo * p = ::new (addr) Foo;
// do work
p->~Foo(); // done

(Just replace Foo by LOCK for your situation.)

However, it gets more complicated: vector and string require dynamic allocations themselves. That memory must live in the same address space as your LOCK. So the standard way to solve this is to write your own allocator and pass that:

template <template <typename> class Alloc>
struct Lock
{
  typedef std::basic_string<char, std::char_traits<char>, Alloc<char>> shared_string;

  shared_string name;
  shared_string type;

  std::vector<shared_string, Alloc<shared_string>> pids;
};

Finally, you have to write a conforming allocator class that puts memory in the same address space as the one in which your LOCK object will ultimately go:

template <typename T>
class shared_allocator { /* write this! */ }

typedef Lock<shared_allocator> LOCK;
查看更多
登录 后发表回答