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

时间:2011-11-18 21:54:36

标签: c++ linux segmentation-fault shared-memory

#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并尝试将LOCK而不是char *写入共享内存。

有人可以帮我解决导致分段错误的问题吗?

3 个答案:

答案 0 :(得分:11)

您将vectorstring放入共享内存。这两个类都分配自己的内存,这些内存将在任何进程生成分配的地址空间内分配,并在从其他进程访问时产生段错误。您可以尝试指定分配器来使用该共享内存,但由于在C ++ 03中假定分配器是无状态的,我不确定它是否可行。

考虑一下Boost.Interprocess如何做到这一点。

答案 1 :(得分:2)

你有很多问题。显而易见的是,你没有构造你的对象。以不透明的形式,您目前正在做:

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

最后,你必须编写一个符合条件的allocator类,它将内存放在与LOCK对象最终到达的地址空间相同的地址空间中:

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

typedef Lock<shared_allocator> LOCK;

答案 2 :(得分:1)

我知道很久以前。但我正在寻找关于共享内存的方法(记住),这个帖子很有趣。

我要求的两分钱:

  • 请注意,读写SharedMemory就像读写文件系统一样。
  • 共享内存ID == file_handle from open(...);

    那么......你如何正确地序列化然后将std :: string甚至std :: vector读写到文件中?你真的从文件中“扩展/缩小”std :: string或std :: vector吗?

谢谢:)