Простая программа с общей памятью на C ++, написанная на Linux: ошибка сегментации - PullRequest
7 голосов
/ 19 ноября 2011
#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; 

} 

Я получил код из учебника по общей памяти.Это работало до тех пор, пока я не определил struct LOCK и не попытался записать LOCKs вместо char * в общую память.

Может кто-нибудь помочь мне разобраться в проблеме, которая вызывает ошибку сегментации?

Ответы [ 3 ]

11 голосов
/ 19 ноября 2011

Вы помещаете vector с и string с в общую память. Оба этих класса выделяют свою собственную память, которая будет выделяться в адресном пространстве любого процесса, который генерирует распределение, и будет вызывать ошибку сегмента при обращении из другого процесса. Вы можете попробовать указать распределители, чтобы использовать эту разделяемую память, но поскольку в C ++ 03 для распределителей предполагается, что они не сохраняют состояние, я не уверен, будет ли это возможно.

Подумайте, как проверить, как это делает Boost.Interprocess.

2 голосов
/ 19 ноября 2011

У вас есть ряд проблем. Очевидным является то, что вы не создаете вашего объекта. В непрозрачной форме вы сейчас делаете:

class Foo;

Foo * p = get_memory();

p->bar = 5;  // ouch!

Что вы должны делать, по крайней мере:

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

(Просто замените Foo на LOCK для вашей ситуации.)

Однако все становится сложнее: vector и string сами требуют динамического выделения. Эта память должна находиться в том же адресном пространстве, что и ваш LOCK. Поэтому стандартный способ решить эту проблему - написать свой собственный распределитель и передать следующее:

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;
};

Наконец, вы должны написать соответствующий класс распределителя, который помещает память в то же адресное пространство, что и пространство, в котором ваш LOCK объект в конечном итоге перейдет:

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

typedef Lock<shared_allocator> LOCK;
1 голос
/ 05 мая 2017

Я знаю, что это очень давно. Но я искал, как (помните) об общих мем, и эта тема интересна.

Два моих цента к демордеру:

  • Обратите внимание, что чтение и запись в SharedMemory точно такие же, как чтение и запись в файловую систему.
  • Идентификатор общей памяти == дескриптор файла из открытого (...);

    Итак ... Как вы ПРАВИЛЬНО сериализуете, а затем читаете и пишете std :: string или даже std :: vector в FILE? Вы действительно «расширяете / уменьшаете» std :: string или std :: vector из ФАЙЛА ??

Спасибо:)

...