在linux上编写的一个简单的c++共享内存程序:分段错误


#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 %pn", shared_memory); 
  /* Determine the segment's size. */ 
  shmctl (segment_id, IPC_STAT, &shmbuffer); 
  segment_size  =               shmbuffer.shm_segsz; 
  printf ("segment size: %dn", 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 %pn", shared_memory); 
  /* Print out the string from shared memory.  */ 
  //printf ("%sn", 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*写入共享内存,它才开始工作。

谁能帮我找出这里导致分割故障的问题?

您将vector s和string s放入共享内存中。这两个类都分配自己的内存,这些内存将在生成分配的进程的地址空间内分配,并且在从另一个进程访问时将产生段错误。您可以尝试指定分配程序来使用共享内存,但由于在c++ 03中分配程序被认为是无状态的,我不确定这是否可能。

考虑查看Boost。

您有许多问题。最明显的一个是,您不需要构造对象。在不透明的形式中,您当前正在做:

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)

然而,它变得更复杂:vectorstring本身需要动态分配。该内存必须与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;

我知道那是很久以前的事了。但是我正在搜索如何(记住)共享内存,这个线程很有趣。

我的两分钱给需方:

  • 请考虑读写SharedMemory就像读写文件系统一样。

  • 共享内存ID == file_handle from open(…);

    所以…你如何正确地序列化,然后读写std::字符串,甚至std::vector到一个文件?你真的"扩展/缩小"std::字符串或std::矢量从一个文件??

谢谢你

最新更新