linux上写的一个简单的C++共享内存程序:segmentation fault

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8189638/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 02:22:20  来源:igfitidea点击:

A simple C++ shared memory program written on linux: segmentation fault

c++linuxsegmentation-faultshared-memory

提问by Terry Li

#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.

我从共享内存教程中获得了代码。它一直有效,直到我定义了 struct LOCK 并尝试将 LOCK 而不是 char* 写入共享内存。

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

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

采纳答案by K-ballo

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.

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

Consider checking out how Boost.Interprocess does it.

考虑看看 Boost.Interprocess 是如何做到的。

回答by Kerrek SB

You have a number of problems. The obvious one is that you don't constructyour 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 Fooby LOCKfor your situation.)

(只需Foo根据LOCK您的情况替换为。)

However, it gets more complicated: vectorand stringrequire 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:

然而,它变得更加复杂: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;
};

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

最后,您必须编写一个符合标准的分配器类,该类将内存放在与您的LOCK对象最终将进入的地址空间相同的地址空间中:

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

typedef Lock<shared_allocator> LOCK;

回答by Bretzelus

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 ??

  • 请考虑读取和写入 SharedMemory 与读取和写入文件系统完全一样。
  • 共享内存 ID == file_handle from open(...);

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

Thank you :)

谢谢 :)